跳至内容

重载

我们可以定义一个 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

也就是说,您可以拥有相同名称但参数数量不同的不同方法,它们将被视为不同的方法。 这称为方法重载

方法通过以下几种标准进行重载

  • 参数的数量
  • 应用于参数的类型限制
  • 必需的命名参数的名称
  • 该方法是否接受 代码块

例如,我们可以定义四个不同的 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 表达式。 为了更明确,您可以在末尾添加一个虚拟的 &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"

但是,编译器无法始终确定顺序,因为并不总存在总排序,因此始终将限制较少的放在最后更好。