为什么Date.new不调用initialize?

时间:2012-01-28 22:17:11

标签: ruby inheritance date

我想创建Date的子类。

一个正常的,健康的,年轻的rubyist,由于Date的实现特性而没有受到干扰,将以下列方式解决这个问题:

require 'date'

class MyDate < Date

  def initialize(year, month, day)
    @original_month = month
    @original_day = day

    # Christmas comes early!
    super(year, 12, 25)
  end

end

继续以最期待的方式使用它......

require 'my_date'

mdt = MyDate.new(2012, 1, 28)

puts mdt.to_s

...只是被事实双重交叉,即Date :: new方法实际上是Date :: civil的别名,它不会永远调用initialize。在这种情况下,最后一段代码打印“2012-01-28”而不是预期的“2012-12-25”。

亲爱的Ruby社区,wtf是这个吗?

是否有一些非常好的理由对 new 进行别名处理,以便它忽略 initialize ,因此,任何常识和对客户程序员心理健康的关注?

1 个答案:

答案 0 :(得分:6)

您定义initialize,但使用new创建新实例。 new返回类的新实例,而不是initialize的结果。

您可以这样做:

require 'date'

class MyDate < Date

  def self.new(year, month, day)
    @original_month = month
    @original_day = day

    # Christmas comes early!
    super(year, 12, 25)
  end

end

mdt = MyDate.new(2012, 1, 28)

puts mdt.to_s

注: @original_month和@original_day在此解决方案中不可用。以下解决方案扩展了日期,因此您可以访问原始月份和日期。对于正常日期,值将为零。

require 'date'

class Date 
  attr_accessor :original_month 
  attr_accessor :original_day
end  

class MyDate < Date

  def self.new(year, month, day)

    # Christmas comes early!
    date = super(year, 12, 25)
    date.original_month = month
    date.original_day = day
    date
  end

end

mdt = MyDate.new(2012, 1, 28)

puts mdt.to_s
puts mdt.original_month

但我建议:

require 'date'

class MyDate < Date

  def self.create(year, month, day)
    @original_month = month
    @original_day = day

    # Christmas comes early!
    new(year, 12, 25)
  end

end

mdt = MyDate.create(2012, 1, 28)

puts mdt.to_s

require 'date'

class Date

  def this_year_christmas
    # Christmas comes early!
    self.class.new(year, 12, 28)
  end

end

mdt = Date.new(2012, 1, 28).this_year_christmas

puts mdt.to_s