对Ruby中的对象感到困惑

时间:2011-02-01 22:14:27

标签: ruby

Ruby新手在这里,

我知道一切都是Ruby中的一个对象,我不确定的一件事是理解Variables。变量基本上给出了对象的参考(如果我错了,请纠正我)。在教学视频中,老师做了一个演示,如下所示:

(IRB)

a = 100
==> 100
b = a
==> 100
b
==> 100

这部分我得到了,完全有道理。

然后他做了

a = 50
==> 50
b
==> 100

如果B应该指向设置为100的那个,为什么如果a现在设置为50,b仍然指向100?

3 个答案:

答案 0 :(得分:9)

这是很酷的事情,100也是一个对象。因此a指向常量对象100,当您分配b = a时,您将b分配给指向对象100的指针,而不指向a的指针1}}或甚至由a持有的值100。

要看到这是真的,请尝试:

irb> puts 100.object_id
=> 201

酷吧?

这里是我前一段时间写过的Ruby对象模型的一点解释。它不是特定于您的问题,而是增加了一些关于Ruby对象模型如何工作的知识:

当您创建对象的实例时,您创建的是一个新对象,其中包含一组实例变量和一个指向该对象类的指针(以及一些其他内容,如对象ID和指向超类的指针) )但方法本身不在对象的实例中。类定义包含方法列表及其代码(以及指向其自己的类的指针,指向其超类的指针和对象ID)。

当您在实例上调用方法时,Ruby会查找实例的类,并在该类的方法列表中查找您调用的方法。如果找不到,那么它会在类的超类中查找。如果它没有在那里找到它,它会查看该类的超类,直到它用完超类。然后它返回到第一个类并查找method_missing方法。如果它找不到它,那么它会进入超类,依此类推,直到它到达设计为引发错误的根对象。

比方说,你有一个Person类,你用这个变量bubba创建一个类的实例:

class Person
  attr_accessor :dob, :name
  def age
    years = Time.now.year - @dob.year
    puts "You are #{years} year#{"s" if years != 1} old"
  end
  def feed
    puts "nom, nom, nom"
  end
end
bubba = Person.new
bubba.name = "Bubba"
bubba.dob = Time.new(1983,9,26)

类图看起来像这样: alt text

那么在创建静态方法,类/模块方法时会发生什么?好吧,请记住,几乎所有东西都是Ruby中的对象,模块定义是类Class的一个实例。是的,你输入的代码实际上也是一个实例,它是实时代码。使用def self.method_name创建类方法时,您将在对象的实例中创建一个方法,该方法是类/模块定义。

很好,所以你要问的那个类方法在哪里?它是在一个匿名类(也就是单例,特征,鬼类)中定义的,正是出于这个原因而创建的。

回到我们的Person类,如果我们在实例bubba上添加类方法,如下所示:

def bubba.drive_pickup
  puts "Yee-haw!"
end

该方法被放入一个专为该实例创建的特殊单例类中,而单例的超类现在是Person类。这使我们的方法调用链看起来像这样: alt text

实例对象bubba上定义的任何其他方法也将被放入该单例类中。每个实例对象永远不会有多个单例类。

因此,为了解决这个问题的原因,模块中的静态方法是在单例类中为模块定义的实例定义的。当您从模块中包含或扩展时,您将添加指向模块的方法表的指针,但不添加模块的单例类的实例对象的方法表。

这样想:如果你创建一个类型为Z的实例x和一个类型为Z的实例y应该x知道y?不,除非特别说明,否则不会。那么混合在另一个模块中的模块也不应该知道其他一些恰好将第一个模块作为其超类的对象。

为了更好地解释Ruby对象模型,观看这个令人敬畏的博客Dave Thomas(不,不是Wendy的家伙)的精彩免费视频:
http://scotland-on-rails.s3.amazonaws.com/2A04_DaveThomas-SOR.mp4

在观看了那段视频之后,我从Pragmatic购买了Dave Thomas的整个series on the Ruby object model,这非常值得。

P.S。任何人都可以随意纠正我忘记的任何事情;就像对象中的具体内容一样。

答案 1 :(得分:2)

b = a并不意味着:b等于a。这意味着:让b引用a指的同一个对象。 如果您以后决定引用另一个对象

a=50

然后b仍然引用旧对象。

这就像你有一只狗并决定将它命名为Charles(Charles = a Dog)。稍后,您还会使用Charlie这个名字作为狗。 (查理=查尔斯)。狗不介意有多少名字指的是他,这是同一只老狗。

再过一段时间你会得到一条金鱼,你决定查尔斯是一条比金鱼更好的名字(查尔斯=金鱼)。在Ruby中,狗现在仍然被命名为查理。

请注意,如果狗根本没有名字,他最终会收集垃圾。

答案 2 :(得分:1)

请记住,变量引用(或保持),而不是对其他变量的引用。因此,当您指定b = a时,您说“让b保持当前持有的值”。所以“a”和“b”是碰巧保持相同参考的单独变量。您可以更改任何一个而不影响另一个。