継承について

継承を使ったコードを書いてみる。

rubyに標準で存在するArrayクラスを継承したクラスMyArrayをつくってみる。
このMyArrayクラスは、Arrayクラスとは異なり、要素のならびをシャッフルするshuffleメソッドを持っている。

class MyArray < Array #MyArrayはArrayを継承している。
  def self.[] *a #あまり重要じゃない。
    MyArray.new(a)
  end

  def shuffle #Arrayには定義されていないメソッド
    sort_by{rand} #シャッフルする。
  end
end

オブジェクトの生成

Arrayクラスのオブジェクト、自分で作ったMyArrayクラスのオブジェクトを生成してみて、それぞれの挙動の違いを見てみる。

a = [1,2,3,4]
ma = MyArray[1,2,3,4]
p a 
p ma
#=>[1, 2, 3, 4] #Arrayクラスのオブジェクト
#=>[1, 2, 3, 4] #MyArrayクラスのオブジェクト

p a.class #=>Array
p ma.class #=>MyArray

Arrayクラスのオブジェクト「a」とMyArrayクラスのオブジェクト「ma」を作った。

MyArrayはArrayクラスを継承しているので、Arrayクラスの持っているメソッドが使えるはず

p a.respond_to?(:map)
p ma.respond_to?(:map)
#=>true Arrayクラスのオブジェクトはmapメソッドを持っている。
#=>true MyArrayクラスのオブジェクトはmapメソッドをっている。

#だから、どちらでも使える。
p a.map{|e| e*e} #=>[1, 4, 9, 16]
p ma.map{|e| e*e} #=>[1, 4, 9, 16]

a, maどちらでもmapを使ってそれぞれの要素を2乗する処理を行うことができた。
maはaのクラスで定義されているメソッドを使うことができる。
(MyArrayクラスはArrayクラスを継承しているので)

今度はMyArrayクラスで定義したメソッドについて調べてみる。

p a.respond_to?(:shuffle)
p ma.respond_to?(:shuffle)
#=>false #Array classはshffleメソッドを持っていない。
#=>true  #MyArray classはshuffleメソッドを持っている。

#p a.shuffle #定義されてないから呼べない。(エラーになる)
p ma.shuffle #定義されているから呼べる。
#=>[3, 4, 2, 1] #シャッフルされた

MyArrayクラス定義されたshuffleメソッドは、

  • aでは使えない(Arrayクラスのオブジェクト)
  • maでは使える (MyArrayクラスのオブジェクト)

まとめ

継承を使うと、継承元クラスのメソッドを継承先のクラスのオブジェクトで使うことができる。
継承先のクラス*1で定義したメソッドは継承元のクラスに影響を与えない。

*1:今回の例ではMyArray