Noobie ... Simple Inheriting from Hash Question ..

Discussion in 'Ruby' started by Neville Burnell, May 18, 2005.

  1. Hi,

    I have a class inheriting from Hash which has some specific methods
    operating on the hash elements:

    Class MyHash < Hash

    def foo
    ...
    end

    End

    ....

    Now, with Hash class, its really easy to create a new hash, eg

    h =3D {:key1 =3D> "val1", :key2 =3D> "val2"}

    What I would like to do is create a new instance of the class with the
    same simplicity, but I'd like to avoid creating a redundant Hash and
    tranferring the contents one by one to MyHash which happens if I code:

    h =3D MyHash.new:)key1 =3D> "val1", :key2 =3D> "val2")

    and then define initialize(h=3D{})

    Whats the "ruby way" tm for something like this?

    Thanks

    Nev







    =20
    Neville Burnell, May 18, 2005
    #1
    1. Advertising

  2. You could just extend the hash class, rather than inheriting from it.
    That is, instead of this:

    class myHash < Hash
    def foo
    ...
    end
    end

    Do this:

    class Hash
    def foo
    ...
    end
    end

    Then, all your hash objects will be given your 'foo' method and you can
    do things like this:

    {:key => "value"}.foo

    David

    Neville Burnell wrote:
    > Hi,
    >
    > I have a class inheriting from Hash which has some specific methods
    > operating on the hash elements:
    >
    > Class MyHash < Hash
    >
    > def foo
    > ...
    > end
    >
    > End
    >
    > ....
    >
    > Now, with Hash class, its really easy to create a new hash, eg
    >
    > h = {:key1 => "val1", :key2 => "val2"}
    >
    > What I would like to do is create a new instance of the class with the
    > same simplicity, but I'd like to avoid creating a redundant Hash and
    > tranferring the contents one by one to MyHash which happens if I code:
    >
    > h = MyHash.new:)key1 => "val1", :key2 => "val2")
    >
    > and then define initialize(h={})
    >
    > Whats the "ruby way" tm for something like this?
    >
    > Thanks
    >
    > Nev
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >



    --
    David Mitchell
    Software Engineer
    Telogis

    NOTICE:
    This message (including any attachments) contains CONFIDENTIAL
    INFORMATION intended for a specific individual and purpose, and
    is protected by law. If you are not the intended recipient,
    you should delete this message and are hereby notified that any
    disclosure, copying, or distribution of this message, or the
    taking of any action based on it, is strictly prohibited.
    David Mitchell, May 18, 2005
    #2
    1. Advertising

  3. Neville Burnell wrote:
    > Hi,
    >
    > I have a class inheriting from Hash which has some specific methods
    > operating on the hash elements:
    >
    > Class MyHash < Hash
    >
    > def foo
    > ...
    > end
    >
    > End
    >
    > ....
    >
    > Now, with Hash class, its really easy to create a new hash, eg
    >
    > h = {:key1 => "val1", :key2 => "val2"}
    >
    > What I would like to do is create a new instance of the class with the
    > same simplicity, but I'd like to avoid creating a redundant Hash and
    > tranferring the contents one by one to MyHash which happens if I code:
    >
    > h = MyHash.new:)key1 => "val1", :key2 => "val2")
    >
    > and then define initialize(h={})
    >
    > Whats the "ruby way" tm for something like this?


    irb(main):001:0> class H < Hash
    irb(main):002:1> def foo; "foo"; end
    irb(main):003:1> end
    => nil
    irb(main):004:0> h = H[1,2,3,4]
    => {1=>2, 3=>4}
    irb(main):005:0> h.class
    => H
    Joel VanderWerf, May 18, 2005
    #3
  4. Hi --

    On Wed, 18 May 2005, David Mitchell wrote:

    > You could just extend the hash class, rather than inheriting from it. That
    > is, instead of this:
    >
    > class myHash < Hash
    > def foo
    > ...
    > end
    > end
    >
    > Do this:
    >
    > class Hash
    > def foo
    > ...
    > end
    > end
    >
    > Then, all your hash objects will be given your 'foo' method and you can do
    > things like this:
    >
    > {:key => "value"}.foo


    This will work but also suffers from the usual problem with extending
    core classes -- namely, it's unsafe to do unless you're sure
    that your code will run in isolation.

    Another possibility is to add the behavior on a per-object basis:

    module MyHashStuff
    def foo
    # ...
    end
    end

    h = {1,2,3,4}
    h.extend(MyHashStuff)
    h.foo # h now has the food method


    David

    --
    David A. Black
    David A. Black, May 18, 2005
    #4
  5. Neville Burnell

    Mark Hubbart Guest

    On 5/17/05, David A. Black <> wrote:
    > Hi --
    >=20
    > On Wed, 18 May 2005, David Mitchell wrote:
    >=20
    > > You could just extend the hash class, rather than inheriting from it. T=

    hat
    > > is, instead of this:
    > >
    > > class myHash < Hash
    > > def foo
    > > ...
    > > end
    > > end
    > >
    > > Do this:
    > >
    > > class Hash
    > > def foo
    > > ...
    > > end
    > > end
    > >
    > > Then, all your hash objects will be given your 'foo' method and you can=

    do
    > > things like this:
    > >
    > > {:key =3D> "value"}.foo

    >=20
    > This will work but also suffers from the usual problem with extending
    > core classes -- namely, it's unsafe to do unless you're sure
    > that your code will run in isolation.
    >=20
    > Another possibility is to add the behavior on a per-object basis:
    >=20
    > module MyHashStuff
    > def foo
    > # ...
    > end
    > end
    >=20
    > h =3D {1,2,3,4}
    > h.extend(MyHashStuff)
    > h.foo # h now has the food method


    Another option is to add a to_myhash method to Hash:

    class MyHash < Hash
    def foo
    ...
    end
    end

    class Hash
    def to_myhash
    MyHash.new.update self
    end
    end

    Now you can create myhashes like this:

    {1=3D>2,3=3D>4}.to_myhash

    cheers,
    Mark
    Mark Hubbart, May 18, 2005
    #5
  6. Mark Hubbart wrote:
    > On 5/17/05, David A. Black <> wrote:
    >> Hi --
    >>
    >> On Wed, 18 May 2005, David Mitchell wrote:
    >>
    >>> You could just extend the hash class, rather than inheriting from
    >>> it. That is, instead of this:
    >>>
    >>> class myHash < Hash
    >>> def foo
    >>> ...
    >>> end
    >>> end
    >>>
    >>> Do this:
    >>>
    >>> class Hash
    >>> def foo
    >>> ...
    >>> end
    >>> end
    >>>
    >>> Then, all your hash objects will be given your 'foo' method and you
    >>> can do things like this:
    >>>
    >>> {:key => "value"}.foo

    >>
    >> This will work but also suffers from the usual problem with extending
    >> core classes -- namely, it's unsafe to do unless you're sure
    >> that your code will run in isolation.
    >>
    >> Another possibility is to add the behavior on a per-object basis:
    >>
    >> module MyHashStuff
    >> def foo
    >> # ...
    >> end
    >> end
    >>
    >> h = {1,2,3,4}
    >> h.extend(MyHashStuff)
    >> h.foo # h now has the food method

    >
    > Another option is to add a to_myhash method to Hash:
    >
    > class MyHash < Hash
    > def foo
    > ...
    > end
    > end
    >
    > class Hash
    > def to_myhash
    > MyHash.new.update self
    > end
    > end
    >
    > Now you can create myhashes like this:
    >
    > {1=>2,3=>4}.to_myhash


    Note though, that this is exactly what the original poster tried to
    avoid - the intermediate hash.

    Another option that hasn't been mentioned yet is to use delegation. You
    can have a wrapper around a hash that contains all your additional methods
    and references a Hash instance.

    Kind regards

    robert
    Robert Klemme, May 18, 2005
    #6
  7. Neville Burnell

    Christoph Guest

    David A. Black schrieb:

    >
    > This will work but also suffers from the usual problem with extending
    > core classes -- namely, it's unsafe to do unless you're sure
    > that your code will run in isolation.
    >
    > Another possibility is to add the behavior on a per-object basis:
    >
    > module MyHashStuff
    > def foo
    > # ...
    > end
    > end
    >
    > h = {1,2,3,4}
    > h.extend(MyHashStuff)
    > h.foo # h now has the food method


    Jet another possibility (it's a pretty rare animal, I've never seen in
    the wild)
    is to clone a core class and alter the clone - For example, it should be
    straight
    forward to reimplement the Set class as a clone of the Hash class.

    ---
    Set = Hash.clone

    class Set
    # aliasing stuff is half the rent ...
    alias :each , :each_key
    alias :include? , :is_key?

    private
    # a couple of original method are be private.
    alias :_implement_add, , :store

    # throw out superfluous original methods
    ['[]', '[]=',:each_key,:each_value, :store,:is_key? ... ].each {|m|
    remove_method(m) }


    public
    # build the methods
    def add(o)
    _implement_add(o,true)
    end
    ...
    end

    ---
    Note I am not advocating a rewrite of the Set class (if at all it
    it should be a c-extension), it just makes a poster child example
    for this idiom.

    /Christoph
    Christoph, May 18, 2005
    #7
    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. lallous

    Noobie question about Switch

    lallous, Dec 26, 2003, in forum: C++
    Replies:
    6
    Views:
    333
    Chris Mantoulidis
    Dec 27, 2003
  2. Replies:
    0
    Views:
    337
  3. Shaun
    Replies:
    2
    Views:
    556
    Simon Brunning
    Apr 22, 2005
  4. Bit Byte
    Replies:
    1
    Views:
    836
    Teemu Keiski
    Jan 28, 2007
  5. rp
    Replies:
    1
    Views:
    517
    red floyd
    Nov 10, 2011
Loading...

Share This Page