Spec-Zone.ru › Crystal

Перегрузка

Мы можем определить метод 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"

Однако компилятор не всегда может определить порядок, поскольку не всегда существует полный порядок, поэтому менее строгие методы лучше всегда размещать в конце.

To the extent possible under law, the persons who contributed to this workhave waived
all copyright and related or neighboring rights to this workby associating CC0 with it.
https://crystal-lang.org/reference/1.2/syntax_and_semantics/overloading.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API