Ruby子类实例变量可以_overwrite_超类(相同的名称)吗? [英] Can Ruby subclass instance variables _overwrite_ the superclass's (same name)?

查看:86
本文介绍了Ruby子类实例变量可以_overwrite_超类(相同的名称)吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在"ruby​​编程语言"一书的第7.3.5节继承和实例变量"中说:

In the Chapter 7.3.5 "Inheritance and Instance Variables" of the book "the ruby programing language" says :

因为实例变量与之无关 继承,子类使用的实例变量不能阴影" 超类中的实例变量.如果子类使用相同的实例变量 名称作为其祖先之一使用的变量,它将覆盖其祖先的值 多变的.可以有意进行此操作以更改祖先的行为,或者可以 不经意间做.在后一种情况下,几乎可以确定会导致错误.与 先前描述的私有方法的继承,这是为什么它只是唯一的另一个原因 熟悉(并控制)Ruby类时,可以安全地扩展Ruby类 超类的实现.

Because instance variables have nothing to do with inheritance, it follows that an instance variable used by a subclass cannot "shadow" an instance variable in the superclass. If a subclass uses an instance variable with the same name as a variable used by one of its ancestors, it will overwrite the value of its >ancestor’s variable. This can be done intentionally, to alter the behavior of the ancestor, or it can be done inadvertently. In the latter case, it is almost certain to cause bugs. As with the inheritance of private methods described earlier, this is another reason why it is only safe to extend Ruby classes when you are familiar with (and in control of) the implementation of the superclass.

我进行了自己的测试,但似乎子类的实例变量不会影响超类

I had made my own test , but seems instance variables from subclass does NOT affect the superclass

我的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 < Point
   attr_accessor :x,:y,:z
   def initialize(x,y,z)
     @x=x
     @y=y
     @z=z
   end
end

irb(main):052:0> p=Point.new(1,2)
=> #<Point:0x87e8968 @x=1, @y=2>
irb(main):053:0> q=Point3D.new(4,5,6)
=> #<Point3D:0x87e423c @x=4, @y=5, @z=6>
irb(main):054:0> q.x
=> 4
irb(main):055:0> p.x
=> 1
irb(main):056:0> 

推荐答案

这本书(强调和加法):

The book (emphasis and addition mine):

如果子类使用与其祖先之一使用的[n instance]变量同名的 instance 变量,它将覆盖其祖先的值变量.

If a subclass uses an instance variable with the same name as a[n instance] variable used by one of its ancestors, it will overwrite the value of its ancestor’s variable.

我知道您没有同一个类的两个实例;我们正在专门讨论继承.

I know you don't have two instances of the same class; we're specifically discussing inheritance.

当子类使用与超类使用的实例变量同名的实例变量时,会有一个实例变量.如果子类更改了该实例变量的值,并且超类对其进行了访问,则它将获取由子类设置的值.

When a subclass uses an instance variable with the same name as an instance variable used by the superclass, there's a single instance variable. If the subclass changes the value of that instance variable, and the superclass accesses it, it gets the value set by the subclass.

实例化一个子类时,它会作为",同时也是超类的一个实例. Ruby的实现方式意味着,如果超类具有实例变量@foo,则子类可以访问它.这使子类的@foo和超类的@foo毫无意义.

When a subclass is instantiated, it acts "as-if" it's also an instance of the superclass. The way Ruby is implemented means that if the superclass has an instance variable @foo, the subclass can access it. This makes a distinction between the subclass's @foo and the superclass's @foo meaningless.

这是子类可能会改变超类行为的方式:通过设置超类可能使用的值.如果子类设置了@foo = 42,并且超类方法访问了@foo,则会看到42.这可能是预期的,也可能不是预期的,因此发出警告.它会导致令人沮丧的调试会话.

This is how subclasses may alter superclass behavior: by setting a value the superclass might use. If a subclass sets @foo = 42, and a superclass method accesses @foo, it sees 42. This may or may not be intended, hence the warning. It can lead to spectacularly frustrating debugging sessions.

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引入了一个错误,因为它无意中使用了与用于容纳堆栈内容的超类数组相同的名称.如果您不熟悉超类的实现,则会引起混乱和错误,直到您深入挖掘以了解意外行为的出处.

TrackingStack introduces a bug, because it inadvertently used the same name as the superclass's array used to hold the stack contents. If you weren't familiar with the superclass's implementation, this would cause confusion and bugs until you dug deeply enough to understand where the unintended behavior came from.

超类的一个实例就是:超类的 instance ,谈论子类 instance 是没有意义的. >会影响它,因为它们是完全不相关的.

An instance of the superclass is just that: an instance of the superclass, and it's meaningless to talk about how an instance of the subclass will affect it, because they're completely unrelated.

在这里改写:

当您不控制或不熟悉超类实现时,子类化可能会有风险.原因之一是因为在子类中引入实例变量可能会覆盖超类实例变量的值,从而导致意外行为.

Subclassing can be risky when you don't control, or are unfamiliar with, the superclass implementation. One reason is because the introduction of an instance variable in the subclass may overwrite the value of a superclass instance variable, leading to unintended behavior.

这篇关于Ruby子类实例变量可以_overwrite_超类(相同的名称)吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆