在Ruby中有没有办法重载初始化构造函数?

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

在爪哇中,可以重载构造函数:

1
2
3
4
5
6
public Person(String name) {
  this.name = name;
}
public Person(String firstName, String lastName) {
   this(firstName +"" + lastName);
}

Ruby中是否有实现相同结果的方法:两个采用不同参数的构造函数?


答案是"是"和"否"。

您可以使用各种机制在其他语言中实现相同的结果,包括:

  • 参数的默认值
  • 变量参数列表(splat运算符)
  • 把你的论点定义为散列

语言的实际语法不允许您定义两次方法,即使参数不同。

考虑到上面的三个选项,可以用下面的示例实现这些选项

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 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链接提供了更多的阅读


我喜欢这样

1
2
3
4
5
6
7
8
9
10
11
12
13
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

但我不知道这是不是最好的方法。


1
2
3
4
5
6
class Person
  def initialize(name, lastName = nil)
    name = name +"" + lastName unless lastName.nil?
    @name = name
  end
end

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
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中声明多个构造函数并模拟重载:

1
2
3
4
5
6
7
8
9
10
11
12
13
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')

签出功能性的Ruby Gem,它的灵感来自于长生不老的模式匹配特性。

1
2
3
4
5
6
   class Foo
     include Functional::PatternMatching

     defn(:initialize) { @name = 'baz' }
     defn(:initialize, _) {|name| @name = name.to_s }
   end


我通常这样做:

1
2
3
4
5
6
7
8
9
10
11
12
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"