Noobie ... Simple Inheriting from Hash Question

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

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.

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

Hi --

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

···

On Wed, 18 May 2005, David Mitchell wrote:

--
David A. Black
dblack@wobblini.net

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

cheers,
Mark

···

On 5/17/05, David A. Black <dblack@wobblini.net> 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

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

Mark Hubbart wrote:

Hi --

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

···

On 5/17/05, David A. Black <dblack@wobblini.net> wrote:

On Wed, 18 May 2005, David Mitchell wrote: