How to derive from DateTime?

Discussion in 'Ruby' started by luisealvarezb, Sep 18, 2009.

  1. Hi, everybody:

    I have been tring to derive a class from DateTime and in doing so have
    come across some nasty problems: it turns out overriding the
    constructor is not straight forward at all. I was looking for some
    pointers, anyone????
    Here is what I have:

    require 'rubygems'
    #~ require 'ruby-debug'

    require 'date'
    class Event < DateTime
    class << self
    alias :eek:ld_new :new
    def new summary, due_date, long_text='', alarm_time=0
    dt = DateTime.parse( due_date )
    obj = old_new(dt.year, dt.month, dt.day, dt.hour, dt.min, dt.sec,
    dt.sg)
    obj.send :initialize, summary, long_text, alarm_time
    obj
    end
    end

    attr_accessor :summary, :long_text, :alarm_time

    def initialize summary, long_text='', alarm_time=0
    @summary = summary
    @long_text = long_text
    @alarm_time = alarm_time
    end
    end

    e = Event.new "something to do", "2009-10-10T00:00"
    puts e.summary
    puts e.year

    e is an event at the end of the code, it has a summary and what ever
    else I pass in but the DateTime structures are not initialized
    correctly. In other words e.year gives me an error and here it is:

    /usr/lib/ruby/1.8/date.rb:492:in `ajd_to_jd': undefined method `+' for
    nil:NilClass (NoMethodError)
    from /usr/lib/ruby/1.8/date.rb:1051:in `__21105__'
    from (eval):4:in `jd'
    from /usr/lib/ruby/1.8/date.rb:1066:in `__21521__'
    from (eval):4:in `civil'
    from /usr/lib/ruby/1.8/date.rb:1081:in `year'
    from D:/workspace/todo/lib/tester.rb:29

    I have tryed some other variants of the code as well and it gets even
    worse. Can any one help, please?
    Bye, Luis
     
    luisealvarezb, Sep 18, 2009
    #1
    1. Advertising


  2. > It looks to me that this is a case where you might be better served by us=

    ing
    > composition and delegation rather than inheritance: instead of an Event
    > being a specialized DateTime=2C it would have a DateTime instance as an
    > instance variable and delegate certain methods (e.g.=2C year=2C etc.) to =

    that
    > instance variable.
    >=20


    I agree with Christopher here. What you want is a proxy class. Here's a way=
    you might implement it:

    class Event

    def self.new( *args )


    class << datetime =3D DateTime.new(*args)

    def sweet

    "what a sweet method"

    end

    end

    datetime


    end

    end


    You could also try this way:


    class Event
    instance_methods.each { |m| undef_method m unless m =3D~ /(^__|^send$|^=
    object_id$)/ }

    def initialize(*args)


    @date_time =3D DateTime.new(*args)


    end

    def method_missing(name=2C *args=2C &block)
    @date_time.send(name=2C *args=2C &block)
    end
    end


    I'm sure you can figure out what's happening here=2C and how to merge it wi=
    th your own code.

    - Ehsan
    =0A=
    _________________________________________________________________=0A=
    Bing=99 brings you maps=2C menus=2C and reviews organized in one place. =
    Try it now.=0A=
    http://www.bing.com/search?q=3Drestaurants&form=3DMLOGEN&publ=3DWLHMTAG&cre=
    a=3DTEXT_MLOGEN_Core_tagline_local_1x1=
     
    Ehsanul Hoque, Sep 19, 2009
    #2
    1. Advertising

  3. On Sep 18, 7:19 pm, Ehsanul Hoque <> wrote:
    > > It looks to me that this is a case where you might be better served by using
    > > composition and delegation rather than inheritance: instead of an Event
    > > being a specialized DateTime, it would have a DateTime instance as an
    > > instance variable and delegate certain methods (e.g., year, etc.) to that
    > > instance variable.

    >
    > I agree with Christopher here. What you want is a proxy class. Here's a way you might implement it:
    >
    > class Event
    >
    >   def self.new( *args )
    >
    >     class << datetime = DateTime.new(*args)
    >
    >       def sweet
    >
    >         "what a sweet method"
    >
    >       end
    >
    >     end
    >
    >     datetime
    >
    >   end
    >
    > end
    >
    > You could also try this way:
    >
    > class Event
    >     instance_methods.each { |m| undef_method m unless m =~ /(^__|^send$|^object_id$)/ }
    >
    > def initialize(*args)
    >
    >   @date_time = DateTime.new(*args)
    >
    > end
    >
    >         def method_missing(name, *args, &block)
    >           @date_time.send(name, *args, &block)
    >         end
    > end
    >
    > I'm sure you can figure out what's happening here, and how to merge it with your own code.
    >
    > - Ehsan
    >
    > _________________________________________________________________
    > Bing™  brings you maps, menus, and reviews organized in one place.   Try it now.http://www.bing.com/search?q=restaurants&form=MLOGEN&publ=WLHMTAG&cre...


    Thank you for that code it looks like a good solution and will use
    it. However, I am left wondering why this anomaly with the
    constructors in DateTime, does that not violate OO practices. How can
    you not be able to inherit from a Class X and redefine it.

    Thanks a lot...
     
    luisealvarezb, Sep 19, 2009
    #3

  4. >=20
    > Thank you for that code it looks like a good solution and will use
    > it. However=2C I am left wondering why this anomaly with the
    > constructors in DateTime=2C does that not violate OO practices. How can
    > you not be able to inherit from a Class X and redefine it.
    >=20
    > Thanks a lot...
    >=20


    Actually=2C there's no anomaly really=2C as far as I know. There's some bug=
    in the code. I have no idea where=2C your code seems fine to me=2C and it =
    could just be because of the way the DateTime class was implemented. But yo=
    u can in fact redefined constructors=2C and it works fine. Try this for exa=
    mple (just an adaptation of your code):

    class Foo
    def initialize(x)
    @x =3D x
    @message =3D "message from foo"
    end
    attr_accessor :message=2C :x
    end

    class Bar < Foo
    class << self
    alias :eek:ld_new :new
    def new(x)
    obj =3D old_new
    obj.send :initialize
    obj
    end
    end
    =20
    def initialize
    @message =3D "message from bar"
    end
    =20
    attr_accessor :message
    end



    f =3D Foo.new(0)


    f.message #=3D> "message from foo"

    f.x #=3D> 0

    b =3D Bar.new(0)

    b.message #=3D> "message from bar"
    b.x #=3D> nil (I actually don't understand why this is=2C someone=
    else might be able to explain)

    =0A=
    _________________________________________________________________=0A=
    Bing=99 brings you maps=2C menus=2C and reviews organized in one place. =
    Try it now.=0A=
    http://www.bing.com/search?q=3Drestaurants&form=3DMLOGEN&publ=3DWLHMTAG&cre=
    a=3DTEXT_MLOGEN_Core_tagline_local_1x1=
     
    Ehsanul Hoque, Sep 19, 2009
    #4
  5. On Sep 19, 12:58 am, Ehsanul Hoque <> wrote:
    > > Thank you for that code it looks like a good solution and will use
    > > it.  However, I am left wondering why this anomaly with the
    > > constructors in DateTime, does that not violate OO practices. How can
    > > you not be able to inherit from a Class X and redefine it.

    >
    > > Thanks a lot...

    >
    > Actually, there's no anomaly really, as far as I know. There's some bug in the code. I have no idea where, your code seems fine to me, and it could just be because of the way the DateTime class was implemented. But you can in fact redefined constructors, and it works fine. Try this for example (just an adaptation of your code):
    >
    > class Foo
    >   def initialize(x)
    >     @x = x
    >     @message = "message from foo"
    >   end
    >   attr_accessor :message, :x
    > end
    >
    > class Bar < Foo
    >   class << self
    >     alias :eek:ld_new :new
    >     def new(x)
    >       obj = old_new
    >       obj.send :initialize
    >       obj
    >     end
    >   end
    >
    >   def initialize
    >     @message = "message from bar"
    >   end
    >
    >   attr_accessor :message
    > end
    >
    > f = Foo.new(0)
    >
    > f.message   #=> "message from foo"
    >
    > f.x       #=> 0
    >
    > b = Bar.new(0)
    >
    > b.message       #=> "message from bar"
    > b.x         #=> nil   (I actually don't understand why this is, someone else might be able to explain)
    >
    > _________________________________________________________________
    > Bing™  brings you maps, menus, and reviews organized in one place.   Try it now.http://www.bing.com/search?q=restaurants&form=MLOGEN&publ=WLHMTAG&cre...


    Specializing other classes works fine but DateTime fails...I see, yeah
    I can't explain it either. Ok, I will just go with what I have.
    Thanks a lot.
     
    luisealvarezb, Sep 19, 2009
    #5
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Christos TZOTZIOY Georgiou
    Replies:
    3
    Views:
    710
    Christos TZOTZIOY Georgiou
    Sep 13, 2003
  2. Tim Peters
    Replies:
    0
    Views:
    536
    Tim Peters
    Sep 9, 2003
  3. mp
    Replies:
    1
    Views:
    392
    John Machin
    Jul 28, 2006
  4. Martin
    Replies:
    0
    Views:
    338
    Martin
    Dec 27, 2008
  5. Replies:
    2
    Views:
    762
    M.-A. Lemburg
    Jan 6, 2009
Loading...

Share This Page