<分区>
在这两篇文章中:
Instance Variables Inheritance
Can Ruby subclass instance variables _overwrite_ the superclass's (same name)?
人们在写关于在所有 OOP 语言中父类(super class)和派生类如何没有单独的对象,并且当您创建派生类的实例时,它也是父类(super class)的实例。有一个对象,它同时是两个类。
嗯,问题是我不明白?一个对象怎么能同时是两个类呢?如果实例变量当然使用相同的名称,它们怎么可能相同?
我的意思是我知道子类从父类(super class)获取方法,但我不明白它们如何共享实例变量?
我已经阅读了至少四本 Ruby 书籍,但我发现的全部内容是实例变量不通过继承链共享?
有人可以简要解释一下子类中的“实例变量”实际上是如何以及为什么存储在父类(super class)中的吗?
这里要理解的关键是:实例变量与当前对象(或实例)关联,而方法与类关联。
这样做的原因是,如果创建的每个对象都与该类的所有其他对象具有相同的主体,那么您不希望为创建的每个对象都创建新方法。
另一方面,每个对象的实例变量必须是单独的,否则在改变值时你将得到一个完整的混搭。
考虑到这一点,让我们考虑以下示例:
class Foo
def foo
@var = :foo
end
end
class Bar < Foo
def bar
@var = :bar
end
end
让我们探索一下当我们创建一个新对象时会发生什么:
baz = Bar.new
目前,baz
没有任何实例变量。它只有一个指针,上面写着“Bar
is my class”。
baz.class # => Bar
Foo
或 Baz
类没有任何诸如 @var
的关联。所以目前,没有人知道@var
。
当你在
baz
上调用一个方法时,方法定义在
Bar
ancestors chain 中搜索:
baz.class.ancestors # => [Bar, Foo, Object, Kernel, BasicObject]
这里可以注意几点:首先,那里的东西是按继承顺序出现的。其次,Foo
隐式继承自Object
。第三,模块也可以是链的一部分(如 Kernel
)。
baz.bar # => :bar
将找到链中第一个有方法 #bar
的东西并调用它。该值被分配给 @var
实例变量,它与对象 baz
关联,而不是类 Foo
或 Bar
.
baz.foo # => :foo
现在将使用 Foo
中的方法定义。但同样,@var
在 baz
中被更改。
一些供日后阅读的相关内容 (为简单起见,上面的一些内容并不完全准确):
- 单例类
- 类变量
- 包括/前置模块
Class.superclass # => 模块
BasicObject#method_missing