プログラミング入門(5)〜クラスの継承

下記のページを参考にプログラミングの勉強を行います。
クラスを継承する - クラスの継承 - Ruby入門
メソッドのオーバーライド - クラスの継承 - Ruby入門
スーパークラスのメソッドを呼び出す - クラスの継承 - Ruby入門
引数があるスーパークラスのメソッドを呼び出す - クラスの継承 - Ruby入門

クラスを継承する


クラスを継承する


クラスはオブジェクトの元になる設計書のようなものだと勉強してきたが、利用したいすべてのクラスを1から作成していると大変だし、共通する部分も複数のクラスの重複して定義する必要がある。

そこで、あるクラスが既に作成されていて、そのクラスを拡張して新しいクラスを作成することが可能であり、このように他のクラスをベースとして新しいクラスを作成することをクラスの継承という。

例えば、車という基本的なクラスを作成しておいて、そのクラスを継承して個別の車種のクラスを作成することができるようになる。車という基本機能に関する部分だけを別のクラスとして定義しておき、個別の車については車のクラスを継承して差分だけを個別に定義するといったことになる。

クラスの継承の仕方


まずは基本となるクラスである「Car」クラスを定義する。

class Car
  def accele
    print("アクセルを踏みました\n")
  end

  def brake
    print("ブレーキを踏みました\n")
  end
end

次に「Car」クラスを継承した「Soarer」クラスを作成してみる。
クラスを継承するにはクラス名の後に「<」をつけて継承したいクラス名を記述する。

class クラス名 < 継承したいクラス

end

よって、次のように記述する。

class Car
  def accele
    print("アクセルを踏みました\n")
  end

  def brake
    print("ブレーキを踏みました\n")
  end
end

class Soarer < Car
  def openRoof
    print("ルーフを開けました\n")
  end
end

今回は「Soarer」クラスが「Car」クラスを継承している。このとき「Car」クラスは「Soarer」クラスのスーパークラスまたは親クラスといい、「Soarer」クラスは「Car」クラスのサブクラスまたは子クラスという。

クラスを継承した場合、クラス自体で定義されたメソッドの他に親クラスで定義されているメソッドも使用することができる。
先ほどの例でいえば、「Soarer」クラスのオブジェクトは「openRoof」メソッドの他に「accele」メソッドや「brake」メソッドも継承することができる。

サンプルプログラム

class Car
  def accele
    print("アクセルを踏みました\n")
  end

  def brake
    print("ブレーキを踏みました\n")
  end
end

class Soarer < Car
  def openRoof
    print("ルーフを開けました\n")
  end
end

class Crown < Car
  def reclining
    print("シートをリクライニングしました\n")
  end
end

soarer = Soarer.new
soarer.openRoof
soarer.accele

crown = Crown.new
crown.reclining
crown.brake

f:id:ayaketan:20111212163228j:image

クラスを継承することで、共通した部分は基本となるクラスとして抜き出すことができ、その結果プログラムの再利用性も高まり、また必ず備えていなければならないメソッドなどを忘れずに備えることができる。

メソッドのオーバーライド


メソッドのオーバーライド


クラスの継承を利用する場合、スーパークラスで定義されたメソッドをサブクラス側で同じ名前を使ってメソッドを新しく定義しなおすことができる。このようにサブクラス側で同じ名前のメソッドを定義することをメソッドのオーバーライドと呼ぶ。

具体的には次のようにする。

class Car
  def accele
    print("アクセルを踏みました\n")
  end

  def brake
    print("ブレーキを踏みました\n")
  end
end

class Soarer < Car
  def openRoof
    print("ルーフを開けました\n")
  end

  def accele
    print("アクセルを踏み加速しました\n")
  end
end

この例では「Soarer」クラスのオブジェクトを作成し「accel」メソッドを実行した場合には「Soarer」クラスで定義されたメソッドが実行される。

サンプルプログラム

class Car
  def accele
    print("アクセルを踏みました\n")
  end

  def brake
    print("ブレーキを踏みました\n")
  end
end

class Soarer < Car
  def openRoof
    print("ルーフを開けました\n")
  end

  def accele
    print("アクセルを踏み加速しました\n")
  end
end

class Crown < Car
  def reclining
    print("シートをリクライニングしました\n")
  end
end

soarer = Soarer.new
soarer.accele

crown = Crown.new
crown.accele

f:id:ayaketan:20111212163247j:image

同じ「Car」メソッドをスーパークラスに持つサブクラスであっても、メソッドのオーバーライドを行わなかった場合は、スーパークラス側のメソッドがそのまま実行される。

このようにオーバーライドを使うことでスーパークラスで定義されたメソッドをサブクラスで自由に書き換えて使用することが可能。

スーパークラスのメソッドを呼び出す


スーパークラスのメソッドを呼び出す


スーパークラスのメソッドがサブクラスでオーバーライドされた場合に、スーパークラスのメソッドを明示的に呼び出すことが可能。スーパークラスのメソッドを呼び出すには、オーバーライドしたメソッドの中で「super」を使って呼び出す。

具体的には次のようになる。

class Car
  def accele
    print("アクセルを踏みました\n")
  end
end

class Soarer < Car
  def accele
    super
    print("加速しました\n")
  end
end

「super」は特殊なメソッドと考える。メソッドの中で「super」メソッドを実行すると、スーパークラスの中で呼び出されたメソッドと同じメソッド名を持つメソッドを探して実行する。
したがって、上記のサンプルで「Soarer」クラスの「accele」メソッドがオブジェクトから実行された場合、まず「super」メソッドが実行される。「super」メソッドは同名のメソッド名を持つスーパークラスのメソッドを実行するので、スーパークラスの「accele」メソッドで定義されている「print("アクセルを踏みました\n")」が実行され、その次に「print("加速しました\n")」が実行される。

サンプルプログラム

class Car
  def accele
    print("アクセルを踏みました\n")
  end
end

class Soarer < Car
  def accele
    super
    print("加速しました\n")
  end
end

soarer = Soarer.new
soarer.accele

f:id:ayaketan:20111212163305j:image

このようにスーパークラスのメソッドの内容を完全に書き換えるのではなく、スーパークラスのメソッドを利用しつつサブクラス側で追加の機能を記述する形でmwそっ度をオーバーライドすることが可能。

引数があるスーパークラスのメソッドを呼び出す


引数があるスーパークラスのメソッドを呼び出す


スーパークラスのメソッドを呼び出す場合に、引数があるメソッドの場合も通常のメソッドと同じように「super」メソッドに引数をつけて呼び出すことができる。

class Car
  def accele(acceletime)
    print(acceletime, "秒間アクセルを踏みました\n")
  end
end

class Soarer < Car
  def accele(acceletime)
    super(acceletime)
    print("加速しました\n")
  end
end

上記の場合、「Soarer」クラスのオブジェクトから「accele」メソッドを引数をつけて呼び出すと、メソッド内でスーパークラスの「accele」メソッドを引数を付けて呼び出す。

また「super」メソッドを呼び出すときの特別ルールとして、引数を指定せずに「super」メソッドを呼び出した場合には、サブクラスを呼び出したときに渡されてきた引数を付けて呼び出したものと同じことになる。

class Car
  def accele(acceletime)
    print(acceletime, "秒間アクセルを踏みました\n")
  end
end

class Soarer < Car
  def accele(acceletime)
    super
    print("加速しました\n")
  end
end

上記の例では「super」メソッドを引数なしで呼び出しているが、この場合は「super(acceletime)」と呼び出したものと同じ扱いになる。もし明示的に引数なしでスーパークラスのメソッドを呼び出す場合には括弧を省略せずに「super()」と呼び出すことでスーパークラスのメソッドを引数なしで呼び出すことができる。(デフォルト引数が設定されている場合等に限る。)

サンプルプログラム

class Car
  def accele(acceletime)
    print(acceletime, "秒間アクセルを踏みました\n")
  end
end

class Soarer < Car
  def accele(acceletime)
    super
    print("加速しました\n")
  end
end

soarer = Soarer.new
soarer.accele(10)

f:id:ayaketan:20111212163338j:image