作者: rubikitch
日時: 2008/2/15(18:28)
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/