オーバーロード¶
年齢を重ねる年数を示す数を受け取る become_older
メソッドを定義できます。
class Person
getter :age
def initialize(@name : String, @age : Int = 0)
end
def become_older
@age += 1
end
def become_older(years)
@age += years
end
end
john = Person.new "John"
john.age # => 0
john.become_older
john.age # => 1
john.become_older 5
john.age # => 6
つまり、同じ名前でパラメータの数や型が異なる複数のメソッドを持つことができ、それらは別のメソッドとして扱われます。これは *メソッドのオーバーロード* と呼ばれます。
メソッドはいくつかの基準でオーバーロードされます。
- パラメータの数
- パラメータに適用される型制約
- 必須の名前付きパラメータの名前
- メソッドが ブロック を受け入れるかどうか
例えば、4つの異なる become_older
メソッドを定義できます。
class Person
@age = 0
# Increases age by one
def become_older
@age += 1
end
# Increases age by the given number of years
def become_older(years : Int32)
@age += years
end
# Increases age by the given number of years, as a String
def become_older(years : String)
@age += years.to_i
end
# Yields the current age of this person and increases
# its age by the value returned by the block
def become_older(&)
@age += yield @age
end
end
person = Person.new "John"
person.become_older
person.age # => 1
person.become_older 5
person.age # => 6
person.become_older "12"
person.age # => 18
person.become_older do |current_age|
current_age < 20 ? 10 : 30
end
person.age # => 28
yield するメソッドの場合、コンパイラは yield
式があるためこれを把握していることに注意してください。これをより明示的にするには、末尾にダミーの &block
パラメータを追加できます。
class Person
@age = 0
def become_older(&block)
@age += yield @age
end
end
生成されたドキュメントでは、ダミーの &block
メソッドは、記述したかどうかに関わらず常に表示されます。
パラメータの数が同じ場合、コンパイラは制限の少ないものを最後にしてソートしようとします。
class Person
@age = 0
# First, this method is defined
def become_older(age)
@age += age
end
# Since "String" is more restrictive than no restriction
# at all, the compiler puts this method before the previous
# one when considering which overload matches.
def become_older(age : String)
@age += age.to_i
end
end
person = Person.new "John"
# Invokes the first definition
person.become_older 20
# Invokes the second definition
person.become_older "12"
ただし、常に完全な順序があるとは限らないため、コンパイラは常に順序を把握できるとは限りません。そのため、制限の少ないメソッドは最後に配置する方が常に良いでしょう。