Ruby 编程/类和对象
如前所述,Ruby 中的一切都是对象。每个对象都有一个类。要查找对象的类,只需调用该对象的class方法。例如,试试这个
puts "This is a string".class
puts 9.class
puts ["this","is","an","array"].class
puts ({:this => "is", :a => "hash"}).class
puts :symbol.class
无论如何,你应该已经知道这一点。然而,你不知道的是如何创建自己的类和扩展 Ruby 的类。
类的实例是属于该类的对象。例如,"巧克力"是 String 类的实例。你已经知道你可以通过简单地使用引号、方括号、花括号等来创建字符串、数组、哈希、数字和其他内置类型,但你也可以通过new方法来创建它们。例如,my_string = ""与my_string = String.new相同。几乎每个类都有一个new方法:数组、哈希,等等。(一些类,比如整数和数字,没有new
方法。这些类不允许在实例化对象之间存在重复。)当你创建自己的类时,你会使用new方法来创建实例。
类代表对象的类型,例如书籍、鲸鱼、葡萄或巧克力。每个人都喜欢巧克力(可能不正确),所以让我们创建一个巧克力类
class Chocolate
def eat
puts "That tasted great!"
end
end
让我们看一下。类是通过class关键字创建的。之后是类的名称。所有类名必须以大写字母开头。按照惯例,我们对类名使用驼峰式命名法。所以我们会创建像 PieceOfChocolate 这样的类,而不是像 Piece_of_Chocolate 这样的类。
下一节定义了一个类方法。类方法是为特定类定义的方法。例如,String 类具有length方法
# outputs "5"
puts "hello".length
要调用 Chocolate 类实例的eat方法,我们将使用此代码
my_chocolate = Chocolate.new
my_chocolate.eat # outputs "That tasted great!"
你也可以使用send
"hello".send(:length) # outputs "5"
my_chocolate.send(:eat) # outputs "That tasted great!"
来调用方法。然而,使用send很少见,除非你需要创建动态行为,因为我们不需要将方法名指定为文字 - 它可以是一个变量。
请注意,Ruby 中方法的典型定义以关键字 def 开头。
但是,你也可以使用 define_method() 代替,并将它与 .send 结合起来,来调用任意方法
class Foo
self.class_eval {
define_method(:'hey there') { puts 'Hey there man!' }
}
end
foo = Foo.new
foo.send :'hey there' # => Hey there man!
在类的某个方法内部,伪变量self(伪变量是不能更改的变量)指的是当前实例。例如
class Integer
def more
return self + 1
end
end
3.more # -> 4
7.more # -> 8
你也可以创建在类而不是实例上调用的方法。例如
class Strawberry
def Strawberry.color
return "red"
end
def self.size
return "kinda small"
end
class << self
def shape
return "strawberry-ish"
end
end
end
Strawberry.color # -> "red"
Strawberry.size # -> "kinda small"
Strawberry.shape # -> "strawberry-ish"
请注意三种不同的构造ClassName.method_name和self.method_name本质上是相同的 - 在类块中的方法定义之外,self指的是类本身。后者是首选,因为它使更改类名变得容易得多。最后一个构造,class << self,将我们置于类的“元类”(有时称为“本类”)的上下文中。元类是类本身所属的特殊类。但是,在这一点上,你无需担心它。此构造所做的只是允许我们在没有self.前缀的情况下定义方法。