In Ruby is there a way to overload the initialize constructor?

匿名 (未验证) 提交于 2019-12-03 07:50:05

问题:

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" 


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!