В Ruby есть способ перегрузить конструктор initialize?
В Java вы можете перегружать конструкторы:
public Person(String name) {
this.name = name;
}
public Person(String firstName, String lastName) {
this(firstName + " " + lastName);
}
Есть ли способ в Ruby для достижения этого же результата: два конструктора, которые принимают разные аргументы?
Ответы
Ответ 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"