継承 / super / override
Rubyのクラス継承とメソッドオーバーライドの構文です。『super』を使って親クラスのメソッドを呼び出す方法を解説します。
構文
# 親クラスを継承してサブクラスを定義します。
class サブクラス名 < 親クラス名
def initialize(引数)
super(引数) # 親クラスの initialize を呼び出します。
@追加変数 = 値
end
# 親クラスのメソッドをオーバーライドします。
def メソッド名
super # 引数をそのまま渡して親クラスのメソッドを呼び出します。
追加処理
end
def メソッド名(引数)
super(引数) # 特定の引数を渡して呼び出します。
end
end
# 親クラスの確認。
サブクラス.superclass # 直接の親クラスを返します。
サブクラス.ancestors # 継承チェーン全体を配列で返します。
オブジェクト.is_a?(クラス) # そのクラス(またはサブクラス)のインスタンスか判定します。
メソッド一覧
| 構文 / メソッド | 概要 |
|---|---|
| class 子 < 親 | 親クラスを継承したサブクラスを定義します。親のメソッドをすべて引き継ぎます。 |
| super | 同名の親クラスのメソッドを呼び出します。引数はそのまま引き継がれます。 |
| super(args) | 指定した引数で親クラスのメソッドを呼び出します。 |
| super() | 引数なしで親クラスのメソッドを呼び出します(引数の引き継ぎをしません)。 |
| superclass | 直接の親クラスを返すクラスメソッドです。 |
| ancestors | 継承チェーン(クラスとモジュールの順序)を配列で返します。 |
| is_a?(klass) | 指定したクラスのインスタンスまたはサブクラスのインスタンスなら『true』を返します。 |
サンプルコード
sample_inheritance_super.rb
# 親クラスの定義。
class Fighter
attr_reader :name, :technique
def initialize(name, technique)
@name = name
@technique = technique
end
def battle_cry
"#{@name}が「#{@technique}」を放ちました。"
end
def info
"戦士: #{@name}"
end
end
# 子クラスの定義(Fighter を継承)。
class SaiyanFighter < Fighter
attr_reader :race
def initialize(name, race)
super(name, "かめはめ波") # 親クラスの initialize を呼び出します。
@race = race
end
# オーバーライド: 親クラスのメソッドを上書きします。
def info
super + "(#{@race})" # 親の info に追加します。
end
def transform(level)
"#{@name}がスーパーサイヤ人#{level}に変身しました!"
end
end
class NamekianFighter < Fighter
def initialize(name)
super(name, "魔貫光殺砲")
end
end
# インスタンスの生成と使用。
saiyan = SaiyanFighter.new("孫悟空", "サイヤ人")
namekian = NamekianFighter.new("ピッコロ")
puts saiyan.battle_cry # 孫悟空が「かめはめ波」を放ちました。
puts namekian.battle_cry # ピッコロが「魔貫光殺砲」を放ちました。
puts saiyan.info # 戦士: 孫悟空(サイヤ人)
puts saiyan.transform(3) # 孫悟空がスーパーサイヤ人3に変身しました!
# 継承の確認。
puts saiyan.is_a?(SaiyanFighter) # true
puts saiyan.is_a?(Fighter) # true(親クラスも is_a? で true)
puts SaiyanFighter.superclass # Fighter
ruby inheritance_super.rb 孫悟空が「かめはめ波」を放ちました。 ピッコロが「魔貫光殺砲」を放ちました。 戦士: 孫悟空(サイヤ人) 孫悟空がスーパーサイヤ人3に変身しました! true true Fighter
概要
Rubyのクラスは『class 子 < 親』で単一継承を実現します。サブクラスは親クラスのすべてのインスタンスメソッドを引き継ぎ、必要なメソッドだけをオーバーライドできます。
『super』の挙動は記述方法によって異なります。引数なしの『super』は現在のメソッドの引数をそのまま親に渡し、『super()』は引数なしで呼び出し、『super(args)』は指定した引数を渡します。混乱しやすい部分なので、明示的に書くことをお勧めします。
『initialize』で『super』を呼び忘れると、親クラスのインスタンス変数が初期化されません。サブクラスで『initialize』を定義したら、原則として『super』(または必要な初期化処理)を最初に呼ぶようにしてください。
モジュールを使った多重継承の代替手段については『module / include / extend』を、比較演算子のカスタマイズは『Comparable / <=>』を参照してください。
記事の間違いや著作権の侵害等ございましたらお手数ですがこちらまでご連絡頂ければ幸いです。