为什么Date.new不会初始化?

问题描述:

我想创建一个Date的子类。为什么Date.new不会初始化?

一个正常的,健康的,年轻rubyist,按日期的实现会去这个以下列方式的特质无瘢痕:

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 

...只有被出卖的事实,该日期::新方法实际上是一个别名日期::民用,这不永远调用初始化。在这种情况下,最后一段代码打印“2012-01-28”而不是预期的“2012-12-25”。

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

有一些很好的理由混淆,所以它忽略初始化和结果,客户端的程序员的心理健康状况的任何常识和考虑?

+1

通过它的 “好” 的定义是什么? – 2012-01-28 22:21:48

+0

有什么选择?如果你从初始化中调用civil,你已经分配了一个你不需要的对象。 – pguardiario 2012-01-28 23:08:48

+0

那么,它分配和初始化一个对象在同一个方法似乎在语义上是错误的。我的意思是,如果'civil'事实上是'new',为什么不最终调用'initialize'呢?它可能是Date中的一个纯形式,但它可以扩展这个类,而不需要真正的挖掘它的实现细节。因此,我想知道,为什么将“civil”变成“new”的决定可能已经完成了? – jst 2012-01-29 09:50:12

您定义了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不提供这种解决方案。以下解决方案扩展了Date,因此您可以访问原始的月份和日期。对于正常日期,值将为零。

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 
+0

感谢您的好评!我最终重载了'new'方法。看起来很奇怪,对象的分配和初始化发生在一种方法中。 – jst 2012-01-29 09:46:56

+0

在你的'self.create'定义中,实例变量是在类上设置的,而不是实例。在'new'的结果中使用'instance_variable_set'会照顾到这一点;只要确保你仍然返回实例。 – Kelvin 2013-10-09 22:42:52