Подтвердить что ты не робот

В Ruby есть способ перегрузить конструктор initialize?

В Java вы можете перегружать конструкторы:

public Person(String name) {
  this.name = name;
}
public Person(String firstName, String lastName) {
   this(firstName + " " + lastName);
}

Есть ли способ в Ruby для достижения этого же результата: два конструктора, которые принимают разные аргументы?

4b9b3361

Ответ 1

Ответ: Да и Нет.

Вы можете добиться того же результата, что и на других языках, используя различные механизмы, включая: -

  • Значения по умолчанию для аргументов
  • Переменные списки аргументов (оператор splat)
  • Определение аргумента как хеша

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

Учитывая три варианта выше, они могут быть реализованы с вашим примером следующим образом

# As written by @Justice
class Person
  def initialize(name, lastName = nil)
    name = name + " " + lastName unless lastName.nil?
    @name = name
  end
end


class Person
  def initialize(args)
    name = args["name"] + " " + args["lastName"] unless args["lastName"].nil?
    @name = name
  end
end

class Person
  def initialize(*args)
    #Process args (An array)
  end
end

Вы часто встретите второй механизм внутри Ruby-кода, особенно в Rails, поскольку он предлагает лучшее из обоих миров и позволяет некоторому синтаксическому сахару вырабатывать красивый код, в частности, не прилагать хэш-код в фигурных скобках.

Эта ссылка wikibooks дает еще несколько показаний

Ответ 2

Я стараюсь делать

class Person
  def self.new_using_both_names(first_name, last_name)
    self.new([first_name, last_name].join(" "))
  end

  def self.new_using_single_name(single_name)
    self.new(single_name)
  end

  def initialize(name)
    @name = name
  end
end

Но я не знаю, лучший ли это подход.

Ответ 3

class Person
  def initialize(name, lastName = nil)
    name = name + " " + lastName unless lastName.nil?
    @name = name
  end
end

Ответ 4

class StatementItem
  attr_reader :category, :id, :time, :amount

  def initialize(item)
    case item
    when Order
      initialize_with_order(item)
    when Transaction
      initialize_with_transaction(item)
    end
  end

  def valid?
    !(@category && @id && @time && @amount).nil?
  end

  private
    def initialize_with_order(order)
      return nil if order.status != 'completed'
      @category = 'order'
      @id = order.id
      @time = order.updated_at
      @amount = order.price
    end

    def initialize_with_transaction(transaction)
      @category = transaction.category
      @id = transaction.id
      @time = transaction.updated_at
      @amount = transaction.amount
    end

end

Ответ 5

Вы можете использовать konstructor gem, чтобы объявить несколько конструкторов в Ruby и имитировать перегрузку:

class Person
  def initialize(name)
    @name = name
  end

  konstructor
  def from_two_names(first_name, last_name)
    @name = first_name + ' ' + last_name
  end
end

Person.new('John Doe')
Person.from_two_names('John', 'Doe')

Ответ 6

Я обычно делаю:

class Person
  attr_reader :name
  def initialize(first: nil, last: nil)
    @name = [first, last].compact.join(' ')
  end
end

Person.new(first: 'ya').name
# => "ya"

Person.new(first: 'ya', last: 'ku').name
# => "ya ku"