可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
In Java you can overload constructors:
public Person(String name) { this.name = name; } public Person(String firstName, String lastName) { this(firstName + " " + lastName); }
Is there a way in Ruby to achieve this same result: two constructors that take different arguments?
回答1:
The answer is both Yes and No.
You can achieve the same result as you can in other languages using a variety of mechanisms including :-
- Default values for arguments
- Variable Argument lists (The splat operator)
- Defining your argument as a hash
The actual syntax of the language does not allow you to define a method twice, even if the arguments are different.
Considering the three options above these could be implemented with your example as follows
# 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
You will encounter the second mechanism frequently within Ruby code, particularly within Rails as it offers the best of both worlds and allows for some syntactic sugar to produce pretty code, particularly not having to enclose the passed hash within braces.
This wikibooks link provides some more reading
回答2:
I tend to do
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
But I don't know if this is the best approach.
回答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:
You can use konstructor gem to declare multiple constructors in Ruby and imitate overloading:
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:
I usually do:
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"