В Ruby есть способ перегрузить конструктор инициализации?
в Java можно перегружать конструкторы:
public Person(String name) {
this.name = name;
}
public Person(String firstName, String lastName) {
this(firstName + " " + lastName);
}
есть ли способ в Ruby достичь того же результата: два конструктора, которые принимают разные аргументы?
6 ответов:
ответ и да и нет.
вы можете достичь того же результата, что и на других языках, используя различные механизмы, включая :-
- значения по умолчанию для Аргументов
- списки переменных аргументов (оператор 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 link обеспечивает еще некоторое чтение
Я склонен делать
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
но я не знаю, если это лучший подход.
class Person def initialize(name, lastName = nil) name = name + " " + lastName unless lastName.nil? @name = name end end
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
можно использовать 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')