2012-01-28 149 views
6

我想創建一個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

回答

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不提供這種解決方案。以下解決方案擴展了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