継承 / 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 Vehicle
attr_reader :name, :capacity
def initialize(name, capacity)
@name = name
@capacity = capacity
end
def action
"#{@name}の積載量は#{@capacity}kgです。"
end
def info
"車両: #{@name}"
end
end
# 子クラスの定義(Vehicle を継承)。
class Car < Vehicle
attr_reader :body_type
def initialize(name, body_type)
super(name, 500) # 親クラスの initialize を呼び出します。
@body_type = body_type
end
# オーバーライド: 親クラスのメソッドを上書きします。
def info
super + "(#{@body_type})" # 親の info に追加します。
end
def accelerate(speed)
"#{@name}が時速#{speed}kmで加速した。"
end
end
class Truck < Vehicle
def initialize(name)
super(name, 3000)
end
end
# インスタンスの生成と使用。
car = Car.new("vehicle_a", "sedan")
truck = Truck.new("vehicle_b")
puts car.action # vehicle_aの積載量は500kgです。
puts truck.action # vehicle_bの積載量は3000kgです。
puts car.info # 車両: vehicle_a(sedan)
puts car.accelerate(120) # vehicle_aが時速120kmで加速した。
# 継承の確認。
puts car.is_a?(Car) # true
puts car.is_a?(Vehicle) # true(親クラスも is_a? で true)
puts Car.superclass # Vehicle
実行すると次のように出力されます。
ruby inheritance_super.rb vehicle_aの積載量は500kgです。 vehicle_bの積載量は3000kgです。 車両: vehicle_a(sedan) vehicle_aが時速120kmで加速した。 true true Vehicle
概要
Rubyのクラスは『class 子 < 親』で単一継承を実現します。サブクラスは親クラスのすべてのインスタンスメソッドを引き継ぎ、必要なメソッドだけをオーバーライドできます。
『super』の挙動は記述方法によって異なります。引数なしの『super』は現在のメソッドの引数をそのまま親に渡し、『super()』は引数なしで呼び出し、『super(args)』は指定した引数を渡します。混乱しやすい部分なので、明示的に書くことをお勧めします。
『initialize』で『super』を呼び忘れると、親クラスのインスタンス変数が初期化されません。サブクラスで『initialize』を定義したら、原則として『super』(または必要な初期化処理)を最初に呼ぶようにしてください。
モジュールを使った多重継承の代替手段については『module / include / extend』を、比較演算子のカスタマイズは『Comparable / <=>』を参照してください。
記事の間違いや著作権の侵害等ございましたらお手数ですがこちらまでご連絡頂ければ幸いです。