5

本「ルビープログラミング言語」の第7.3.5章「継承とインスタンス変数」では、次のように述べています。

インスタンス変数は継承とは関係がないため、サブクラスで使用されるインスタンス変数は、スーパークラスのインスタンス変数を「シャドウ」することはできません。サブクラスが、その祖先の 1 つによって使用される変数と同じ名前のインスタンス変数を使用する場合、その >祖先の変数の値を上書きします。これは、祖先の動作を変更するために意図的に行うことも、不注意で行うこともできます。後者の場合、ほぼ確実にバグが発生します。前述のプライベート メソッドの継承と同様に、これが、スーパークラスの実装に精通している (そして制御できる) 場合にのみ、Ruby クラスを安全に拡張できるもう 1 つの理由です。

私は自分のテストを作成しましたが、サブクラスのインスタンス変数はスーパークラスに影響を与えないようです

私の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> 
4

2 に答える 2

7

本(強調と追加の鉱山):

サブクラスが、その祖先の 1 つによって使用される [n インスタンス] 変数と同じ名前のインスタンス変数を使用する場合、その祖先の変数の値を上書きします。

同じクラスのインスタンスが 2 つないことはわかっています。継承について具体的に説明しています。

サブクラスが、スーパークラスによって使用されるインスタンス変数と同じ名前のインスタンス変数を使用する場合、単一のインスタンス変数が存在します。サブクラスがそのインスタンス変数の値を変更し、スーパークラスがそれにアクセスすると、サブクラスによって設定された値が取得されます。

サブクラスがインスタンス化されると、スーパークラスのインスタンスであるかのように動作します。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スタックの内容を保持するために使用されるスーパークラスの配列と同じ名前を誤って使用したため、バグが発生しました。スーパークラスの実装に慣れていない場合、意図しない動作がどこから来たのかを理解するのに十分なほど深く掘り下げるまで、これは混乱とバグの原因となります。

スーパークラスのインスタンスはまさにそれです:スーパークラスのインスタンスであり、サブクラスのインスタンスがスーパークラスにどのように影響するかについて話しても意味がありません。それらは完全に無関係だからです。

ここに言い換えがあります:

サブクラス化は、スーパークラスの実装を制御していない場合、または慣れていない場合、危険を伴う可能性があります。理由の 1 つは、サブクラスにインスタンス変数を導入すると、スーパークラスのインスタンス変数の値が上書きされ、意図しない動作が発生する可能性があるためです。

于 2013-01-26T14:16:51.010 に答える
1

インスタンス変数は、クラスではなくインスタンスに属します。「継承」の概念全体は、そこでは意味がありません。継承はクラスにのみ適用されます。

于 2013-01-26T13:45:44.410 に答える