2012-01-28 9 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-12-25"の代わりに "2012-01-28"を出力します。

親愛なるRubyコミュニティでは、wtfはこれですか?

それはを無視するように、新しいをエイリアシングのためのいくつかの非常に良い理由があるがを初期化し、その結果、任意の常識とクライアントのプログラマの精神的健康に関係?

+1

? –

+0

代替手段はありますか? civilizeをinitializeから呼び出すと、必要のないオブジェクトが割り当てられます。 – pguardiario

+0

同じ方法でオブジェクトを割り当てて初期化するのは、意味的に間違っているようです。つまり、「市民」が事実上の「新」であれば、結局は「初期化」と呼ぶのはなぜですか?これは 'Date'の純粋な形式であるかもしれませんが、実装の詳細を実際に掘り下げる必要なしにクラスを拡張することができます。だから私は、「市民」から「新」へのエイリアス決定がなぜなされたのだろうと、私は疑問に思った。 – jst

答えて

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

偉大な答えをありがとう!私は 'new'メソッドのオーバーロードを終わらせました。 1つのメソッドでオブジェクトの割り当てと初期化が行われるのは、非常に奇妙なことです。 – jst

+0

'self.create'定義では、インスタンス変数ではなく、クラスにインスタンス変数が設定されています。 'new'の結果に対して' instance_variable_set'を使用すると、それが処理されます。インスタンスを返すようにしてください。 – Kelvin