sobreescritura - En Ruby, ¿hay una manera de sobrecargar el constructor de inicialización?
sobrecarga de polimorfismo (6)
En Java puedes sobrecargar a los constructores:
public Person(String name) {
this.name = name;
}
public Person(String firstName, String lastName) {
this(firstName + " " + lastName);
}
¿Hay una manera en Ruby de lograr este mismo resultado: dos constructores que toman argumentos diferentes?
La respuesta es ambas, si y no.
Puede lograr el mismo resultado que puede obtener en otros idiomas usando una variedad de mecanismos que incluyen:
- Valores predeterminados para argumentos
- Listas de argumentos variables (el operador splat)
- Definiendo tu argumento como un hash
La sintaxis real del lenguaje no le permite definir un método dos veces, incluso si los argumentos son diferentes.
Teniendo en cuenta las tres opciones anteriores, se podrían implementar con su ejemplo de la siguiente manera
# 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
Con frecuencia, encontrará el segundo mecanismo dentro del código Ruby, particularmente dentro de Rails, ya que ofrece lo mejor de ambos mundos y permite que un poco de azúcar sintáctico produzca un código bonito, particularmente al no tener que encerrar el hash entre llaves.
Este enlace de wikibooks proporciona algo más de lectura.
Por lo general hago
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"
Puede usar la gema konstructor para declarar múltiples constructores en Ruby e imitar la sobrecarga:
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'')
Tiendo a hacer
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
Pero no sé si este es el mejor enfoque.
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