From: kikwai@... (機械伯爵)
Subject: [TSruby:252] Mix-in について
Date: Fri, 15 Feb 2008 16:25:07 +0900 (JST)
るびきちです。
> ・多重継承は継承関係がアヤしくなるのでヤめとこう
> ・でも、オブジェクトをイジるセットを導入したいな
> ・んじゃ、「継承(inheritance)」でなく「混入(Mix-in)」するか……
そうですね。
> そうそう、Mix-inで導入されたメソッド群って、そのクラスが継承されて子ク
> ラスを作った場合、子クラスにも継承されるんですか?(私の感覚では、されて
> 当然と思うのだけど、それは継承がザルなPythonに慣れすぎたせいかもしれない
> し……)
ではMix-inと継承の例を示しましょう。
module Mod
def a_method1
:module_method1
end
def a_method2
:module_method2
end
end
class A
# a_method1とa_method2がMix-inされる。
include Mod
end
class B < A
# Mix-inよりもサブクラスの方が優先されるので、a_method1はオーバーライドされる。
def a_method1
:subclass_method1
end
end
a = A.new # => #<A:0xb7bd3488>
a.is_a? A # => true
a.is_a? Mod # => true
a.kind_of? Mod # => true
a.a_method1 # => :module_method1
a.a_method2 # => :module_method2
b = B.new # => #<B:0xb7bd1d68>
b.is_a? B # => true
b.is_a? A # => true
b.is_a? Mod # => true
b.kind_of? Mod # => true
b.a_method1 # => :subclass_method1
b.a_method2 # => :module_method2
> ・あるオブジェクト(Rubyだとモジュールですっけ?)のメソッドは継承し、使
> えるけど、型を調べるとそのオブジェクトの子クラスじゃない
モジュールはあくまで「インスタンスを作れないクラス(のようなもの)」という感じです。
なので、Mix-inされたモジュールとは「is_a?」関係になります。
けれどもモジュールはクラスではないのでスーパークラスにはなりえません。
継承グラフに「注入」するような感じです。
B.ancestors # => [B, A, Mod, Object, Kernel]
B.superclass # => A
A.superclass # => Object
> あと、この考えで間違いないとすると、Javaのinterfaceとは全く逆の意味で
> の多重継承の利点を利用するためのもの、ということになるわけですよね。
そうですね。本来の多重継承から危険性を取り除いたのがMix-inです。
> ※Rubyはダックタイピングが可能ですから、interfaceはそもそも不要ですしね
そう。オブジェクトがメソッドを受け付けるどうかで決まります。
たとえばARGFはIOっぽいけどIOクラスじゃありません。
IOっぽいのは、IOクラスのメソッドを受け付けるからです。
だから、型をチェックするのではなくてメソッドを受け付けるかチェックするほうがいいのです。
--
rubikitch
Blog: http://d.hatena.ne.jp/rubikitch/
Site: http://www.rubyist.net/~rubikitch/