Ruby可以子类化实例变量_overwrite_超类(同名)吗?
在“ruby编程语言”一书的第7.3.5节“inheritance和实例变量”中说:
因为实例变量与inheritance无关,所以子类使用的实例变量不能“遮蔽”超类中的实例变量。 如果子类使用与其祖先之一使用的变量同名的实例变量,它将覆盖其> ancestor变量的值。 这可以有意地完成,以改变祖先的行为,或者可以无意中完成。 在后一种情况下,几乎可以肯定会导致错误。 与前面描述的私有方法的inheritance一样,这是另一个原因,当您熟悉(并控制)超类的实现时,扩展Ruby类是安全的。
我做了自己的测试,但似乎来自子类的实例变量不会影响超类
我的Ruby版本
bob@bob-ruby:~$ ruby --version ruby 1.9.3p194 (2012-04-20 revision 35410) [i686-linux] bob@bob-ruby:~$
以下是代码
class Point attr_accessor :x,:y def initialize(x,y) @x,@y=x,y end end class Point3D p=Point.new(1,2) => # irb(main):053:0> q=Point3D.new(4,5,6) => # irb(main):054:0> qx => 4 irb(main):055:0> px => 1 irb(main):056:0>
这本书(重点和补充我的):
如果子类使用与其祖先之一使用的[n instance]变量同名的实例变量,则它将覆盖其祖先变量的值。
我知道你没有同一个class级的两个实例; 我们专门讨论inheritance问题。
当子类使用与超类使用的实例变量同名的实例变量时,会有一个实例变量。 如果子类更改了该实例变量的值,并且超类访问它,则它将获取子类设置的值。
当子类被实例化时,它“as-if”它也是超类的一个实例。 实现Ruby的方式意味着如果超类具有实例变量@foo
,则子类可以访问它。 这使得子类的@foo
和超类的@foo
。
这就是子类如何改变超类行为:通过设置超类可能使用的值。 如果子类设置@foo = 42
,并且超类方法访问@foo
,则它看到42
。 这可能是也可能不是,因此警告。 它可能会导致令人沮丧的调试会话。
class MyStack def initialize @my_array = [] end def push(item) @my_array << item end end # Stack class that keeps a list # of every item ever pushed. class TrackingStack < MyStack def initialize super @my_array = [] end def push(item) super @my_array << item end def all_items_ever_pushed @my_array end end
TrackingStack
引入了一个错误,因为它无意中使用了与用于保存堆栈内容的超类数组相同的名称。 如果您不熟悉超类的实现,这将导致混淆和错误,直到您深入挖掘以了解意外行为的来源。
超类的一个实例就是:超类的一个实例 ,谈论子类的实例将如何影响它是没有意义的,因为它们完全不相关。
这是一个改述:
当您不控制或不熟悉超类实现时,子类化可能会有风险。 一个原因是因为在子类中引入实例变量可能会覆盖超类实例变量的值,从而导致意外行为。
实例变量属于实例,而不属于类。 “inheritance”的整个概念在那里甚至没有意义,inheritance只适用于类。