プログラミング入門(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
クラスを継承することで、共通した部分は基本となるクラスとして抜き出すことができ、その結果プログラムの再利用性も高まり、また必ず備えていなければならないメソッドなどを忘れずに備えることができる。
メソッドのオーバーライド
メソッドのオーバーライド
クラスの継承を利用する場合、スーパークラスで定義されたメソッドをサブクラス側で同じ名前を使ってメソッドを新しく定義しなおすことができる。このようにサブクラス側で同じ名前のメソッドを定義することをメソッドのオーバーライドと呼ぶ。
具体的には次のようにする。
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
同じ「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
このようにスーパークラスのメソッドの内容を完全に書き換えるのではなく、スーパークラスのメソッドを利用しつつサブクラス側で追加の機能を記述する形で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)