From: rubikitch Date: 2005-08-20T12:17:14+09:00 Subject: [ruby-list:41048] Re: 親クラスのインスタンスを元に子クラスのインスタンスを作りたい From: Nonta Subject: [ruby-list:41046] Re: 親クラスのインスタンスを元に子クラスのインスタンスを作りたい Date: Sat, 20 Aug 2005 11:33:00 +0900 るびきちです。 > b.method > とすると、4が返ってきてくれずにエラーになってしまいました。 > クラスBで改めて何かを記述する必要があるのでしょうか…。 methodというメソッド名だからだめなのです。 他のメソッド名ならばちゃんと4が返ってきます。 なぜかというと、delegate.rbでは委譲にmethod_missingを使っているからです。 method_missingはとても便利ですが注意して使う必要があります。 自分のクラスでは定義していないメソッドは、まず、スーパークラスへ投げられます。 そして、どんどんクラス階層を上がっていき、Objectへ投げられます。 Objectも知らないメソッドが初めてmethod_missingに投げられるのです。 自分のクラスでは定義していないが、スーパークラスで定義されているメソッドの 場合、method_missingに行かず、スーパークラスのメソッドが呼ばれるのです。 なお、ostruct.rbもmethod_missingを使っています。 # 昔はまりました(^^; Object#method_missing --- method_missing(name, args, ... ) 呼びだされたメソッドが定義されていなかった時、Ruby がこのメソッド を呼び出します。 呼び出しに失敗したメソッドの名前 (Symbol) が name に その時の引数が arg ... に渡されます。 デフォルトではこのメソッドは例外 NameError を発生させます。 しかし、methodというメソッドは定義されているので、うまくいかなかったのです。 Object#method --- method(name) self のメソッド name をオブジェクト化した Method オブジェクトを返します。name は Symbol または文字列で指定します。 Module#instance_method [Module/instance_method] も参照してください。 しかし、forwardableを使うとうまくいきます。 require 'forwardable' class A def initialize() @x = 1 @y = nil end attr_accessor :x attr_accessor :y def method() 4 end end class B extend Forwardable def_delegators(:@a, :method, :x, :y) def initialize(a = A.new) @a = a end end b = B.new #あたかもBはAのサブクラスかのように a = A.new a.y = 2 b = B.new(a) #aのインスタンス変数の値を引き継いだb puts b.method るびきち☆ http://www.rubyist.net/~rubikitch/