类和对象

类是一个对象(class 类的一个实例)外加一组实例方法和一个对其超类的引用。Class 类是 Module 类的子类,因此一个类也是一个模块。

对象是一组实例变量外加一个指向其类的引用。对象的方法存在于对象的类中,得以共享。在类中,这些方法被称为类的实例方法。对象的实例变量存在与对象中,不能共享。

不管处在 Ruby 程序的哪个位置,总是存在一个当前对象 self 和当前类(模块)。

当前对象 self

每一行代码都会在一个对象中被执行,这个对象就是当前对象。当前对象可以用 self来表示。在给定时刻,只有一个对象能充当当前对象。

一、在类定义中,当前对象 self 就是正在定义的类

class MyClass
  puts self.object_id => 70165694007420
end

MyClass.object_id => 70165694007420

二、当调用一个方法时,接收者就成为 self

class MyClass
  def my_method
    puts self.object_id
  end
end

obj = MyClass.new
obj.my_method => 70165694344480
obj.object_id => 70165694344480

所有的实例变量都是 self 的实例变量,任何没有指明接收者的方法都在 self 上调用。

如下,obj为接受者,成为 self。因此,@v 成为 obj 的实例变量,my_methodmy_call 没有指明接收者,在 obj 上调用。

class MyClass
  def my_method
    @v = 1
    my_call()
    puts self.object_id => 70165694244520
  end

  def my_call
    @v = 2
    puts self.object_id => 70165694244520
  end
end

obj = MyClass.new
obj.object_id => 70165694244520
obj.my_method => @v = 2

指明接收者的方法,在被指明的接受者上调用

class MyClass
  def self.my_method
    puts self.object_id
  end
end

MyClass.object_id => 70119468319900
MyClass.my_method => 70119468319900

三、 当遇见 instance_evalclass_eval 时同理

class MyClass
  def initialize
    @v = 1
  end
end

obj = MyClass.new
obj.object_id => 70165689982000
obj.instance_eval do
  puts self.object_id => 70165689982000 (self为块的接收者, obj)
  @v => 1
end

MyClass.class_eval do
  puts self.object_id => 70165694007420 (self为块的接收者, MyClass)
  def my_method
    puts self.object_id (调用方法, self 为该方法的接受者 obj)
  end
end

MyClass.object_id  => 70165694007420
obj.my_method => 70165689982000

当前类

所有使用 def 定义的方法将成为当前类的实例方法。在类定义中,当前类就是 self ,即为正在定义的类。因此,在类定义中,当前类 == 当前对象 == self。

class MyClass
  # 当前类为 MyClass
  @my_var = 1
  # self为MyClass, 因此,@my_var为MyClass的实例变量,为类实例变量
  def my_method
    # my_method为当前类 MyClass 的实例方法
  end
end

笔记来源

Ruby元编程(第2版)