跳转到内容

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_nameself.method_name本质上是相同的 - 在类块中的方法定义之外,self指的是类本身。后者是首选,因为它使更改类名变得容易得多。最后一个构造,class << self,将我们置于类的“元类”(有时称为“本类”)的上下文中。元类是类本身所属的特殊类。但是,在这一点上,你无需担心它。此构造所做的只是允许我们在没有self.前缀的情况下定义方法。

华夏公益教科书