メソッドのオーバーライド
CoddyのRubyジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 23/57。
サブクラスは、同じ名前のメソッドを定義することでメソッドをオーバーライドできます。Rubyはまずオブジェクト自身のクラスでメソッドを探し、その後でスーパークラスを探すため、サブクラスのバージョンが優先されます:
class Animal
def speak
"..."
end
end
class Dog < Animal
def speak
"Woof"
end
end
class Fish < Animal
end
puts Dog.new.speak
puts Fish.new.speak出力:
Woof
...スーパークラスのメソッドが別のメソッドを呼び出す場合、サブクラスのオブジェクトに対してはオーバーライドされたバージョンが使用されます。共有されるメソッドは一度だけ記述し、各サブクラスでは異なる部分だけを変更します。
class Animal
def initialize(name)
@name = name
end
def introduce
"#{@name} says #{speak}"
end
def speak
"..."
end
end
class Cat < Animal
def speak
"Meow"
end
end
puts Cat.new("Tom").introduce
puts Animal.new("Thing").introduce出力:
Tom says Meow
Thing says ...サブクラスで to_s をオーバーライドすると、そのサブクラスだけの表示方法が変わります。オーバーライドしていないメソッドは、引き続きスーパークラスから継承されます。
class Item
def initialize(name, price)
@name = name
@price = price
end
def to_s
format("%s %.2f", @name, @price)
end
end
class SaleItem < Item
def to_s
format("%s %.2f (sale)", @name, @price * 0.8)
end
end
puts Item.new("Lamp", 20)
puts SaleItem.new("Lamp", 20)出力:
Lamp 20.00
Lamp 16.00 (sale)Ruby が検索する順序は、クラスの祖先です。つまり、クラス自体、その後にスーパークラスが続き、Object まで検索されます。そのリストでメソッドを定義している最初のクラスが、そのメソッドを提供します。
class Animal
def speak
"..."
end
end
class Dog < Animal
def speak
"Woof"
end
end
class Puppy < Dog
end
puts Puppy.new.speak
p Puppy.ancestors.take(3)出力:
Woof
[Puppy, Dog, Animal]チャレンジ
簡単給与計算のクラスを完成させてください。Employeeはnameを保持し、hours * 20を返すpay(hours)と、payを使用してAda: 800を返すpayslip(hours)を持ちます。Managerはpayをオーバーライドし、勤務時間にかかわらず固定値1500を返します。Internはpayをオーバーライドし、hours * 12を返しますが、最大300までです。payslipはEmployeeでのみ定義されています。
提供されたコードは、employee Ada 40、manager Bo 50、またはintern Cy 20の行を読み込み、対応するオブジェクトを作成して給与明細を出力し、その後に合計給与を出力します。
コードはemployee.rb、manager.rb、intern.rbに記述します。main.rbには提供された入出力コードが含まれており、編集できません。
自分で試してみよう
require_relative 'employee'
require_relative 'manager'
require_relative 'intern'
# 提供された入出力コード: そのままにしておく
input = []
while (line = gets)
input << line.chomp
end
kinds = { "employee" => Employee, "manager" => Manager, "intern" => Intern }
total = 0
input.each do |line|
kind, name, hours = line.split
worker = kinds[kind].new(name)
puts worker.payslip(hours.to_i)
total += worker.pay(hours.to_i)
end
puts "total: #{total}"
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
オブジェクト指向プログラミングのすべてのレッスン
自分で練習してみよう: Rubyオンラインコンパイラ