[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Noobie ... Simple Inheriting from Hash Question ..

Neville Burnell

5/17/2005 11:59:00 PM

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














6 Answers

David Mitchell

5/18/2005 12:11:00 AM

0

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.


Joel VanderWerf

5/18/2005 12:23:00 AM

0

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


dblack

5/18/2005 2:01:00 AM

0

Mark Hubbart

5/18/2005 3:13:00 AM

0

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

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


Robert Klemme

5/18/2005 7:30:00 AM

0

Mark Hubbart wrote:
> 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
>
> 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

Christoph R.

5/18/2005 12:23:00 PM

0

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