[lnkForumImage]
TotalShareware - Download Free Software

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


 

Forums >

comp.lang.ruby

Instead of templates

Adelle Hartley

3/24/2005 11:16:00 AM

Hi all,

I have some methods that I want to add to several classes.
eg.

class A << MyBaseClass
def self.DoMyThing(klass=self)
...
end
end

class B << MyBaseClass
def self.DoMyThing(klass=self)
...
end
end

class C << B
def self.DoMyThing(klass=self)
...
end
end

If I were writing this in C++, I'd use templates. What's the Ruby Way?

Adelle.



9 Answers

Robert Klemme

3/24/2005 11:22:00 AM

0


"Adelle Hartley" <adelle@bullet.net.au> schrieb im Newsbeitrag
news:courier.4242A14D.00002361@mars.sisgroup.com.au...
> Hi all,
>
> I have some methods that I want to add to several classes.
> eg.
>
> class A << MyBaseClass
> def self.DoMyThing(klass=self)
> ...
> end
> end
>
> class B << MyBaseClass
> def self.DoMyThing(klass=self)
> ...
> end
> end
>
> class C << B
> def self.DoMyThing(klass=self)
> ...
> end
> end
>
> If I were writing this in C++, I'd use templates. What's the Ruby Way?

module Extension
# this one is really only neede if you
# want to inherit this behavior automatically
# down the class hierarchy
def inherited(cl)
cl.extend Extension
end

def do_my_thing(klass=self)
# whatever
p klass
end
end

>> class A
>> extend Extension
>> end
=> A
>> A.do_my_thing
A
=> nil
>> class B < A
>> end
=> nil
>> B.do_my_thing
B
=> nil

Kind regards

robert

gabriele renzi

3/24/2005 11:31:00 AM

0

Adelle Hartley ha scritto:

> If I were writing this in C++, I'd use templates. What's the Ruby Way?

probably mixins using #extend :
>> a=Class.new
=> #<Class:0x2be5788>
>> module M; def foo() 'yuk' end; end
=> nil
>> a.extend M
=> #<Class:0x2be5788>
>> a.foo
=> "yuk"

Adelle Hartley

3/24/2005 3:13:00 PM

0

Hi,

> >
> > If I were writing this in C++, I'd use templates. What's
> the Ruby Way?
>
> module Extension
> # this one is really only neede if you
> # want to inherit this behavior automatically
> # down the class hierarchy
> def inherited(cl)
> cl.extend Extension
> end
>
> def do_my_thing(klass=self)
> # whatever
> p klass
> end
> end
>
> >> class A
> >> extend Extension
> >> end

Close, but no banana.

Maybe I'm not doing it right. Here's what I've got:


class MyBase
def self.do_my_thing(klass=self)
p '-----'
end
end

module Extension
def inherited(cl)
cl.extend Extension
end

def do_my_thing(klass=self)
p klass
super(klass.superclass)
end
end

class A < MyBase
extend Extension
end

class B < A
end

class C < B
end

class D < C
end

D.do_my_thing



My output is:

D
"-----"


The output I want is:

D
C
B
A
"-----"


Is this possible (without repeating the definition of do_my_thing)?

Adelle.



Robert Klemme

3/24/2005 4:29:00 PM

0


"Adelle Hartley" <adelle@bullet.net.au> schrieb im Newsbeitrag
news:courier.4242D8BE.000002FE@mars.sisgroup.com.au...
> Hi,
>
> > >
> > > If I were writing this in C++, I'd use templates. What's
> > the Ruby Way?
> >
> > module Extension
> > # this one is really only neede if you
> > # want to inherit this behavior automatically
> > # down the class hierarchy
> > def inherited(cl)
> > cl.extend Extension
> > end
> >
> > def do_my_thing(klass=self)
> > # whatever
> > p klass
> > end
> > end
> >
> > >> class A
> > >> extend Extension
> > >> end
>
> Close, but no banana.
>
> Maybe I'm not doing it right. Here's what I've got:

You cannot use super here, because super refers to the superclass of the
class instance. All class instances have the same super class hierarchy:

>> String.class.ancestors
=> [Class, Module, Object, Kernel]
>> Fixnum.class.ancestors
=> [Class, Module, Object, Kernel]

You need Class#superclass:

> class MyBase
> def self.do_my_thing(klass=self)
> p '-----'
> end
> end
>
> module Extension
> def inherited(cl)
> cl.extend Extension
> end
>
> def do_my_thing(klass=self)
> p klass

superclass.do_my_thing

> end
> end
>
> class A < MyBase
> extend Extension
> end
>
> class B < A
> end
>
> class C < B
> end
>
> class D < C
> end
>
> D.do_my_thing
>
>
>
> My output is:
>
> D
> "-----"
>
>
> The output I want is:
>
> D
> C
> B
> A
> "-----"
>
>
> Is this possible (without repeating the definition of do_my_thing)?

And, btw, you don't need the class argument. You can print self instead.

?> D.do_my_thing
D
C
B
A
"-----"
=> nil

Kind regards

robert

Adelle Hartley

3/25/2005 1:47:00 AM

0

Robert Klemme wrote:
> You cannot use super here, because super refers to the
> superclass of the class instance. All class instances have
> the same super class hierarchy:
>
> >> String.class.ancestors
> => [Class, Module, Object, Kernel]
> >> Fixnum.class.ancestors
> => [Class, Module, Object, Kernel]
>
> You need Class#superclass:
>
> > class MyBase
> > def self.do_my_thing(klass=self)
> > p '-----'
> > end
> > end
> >
> > module Extension
> > def inherited(cl)
> > cl.extend Extension
> > end
> >
> > def do_my_thing(klass=self)
> > p klass
>
> superclass.do_my_thing
>
> > end
> > end
> >
<snip>
>
> And, btw, you don't need the class argument. You can print
> self instead.
>

Fantastisch!! You have not only shown me how to do what I want but also how
to do it in a truly elegant way.

Adelle.





Mathieu Bouchard

3/26/2005 3:02:00 AM

0

Adelle Hartley

3/26/2005 9:43:00 AM

0

Hi Mathieu,

> class A
> @special={}
> def self.of(t)
> @special[t] ||= Class.new(self) { @mytype=t; ... }
> end
> end

That's a neat idea. I think I will keep that up my sleeve. I am bound to
need it.

>
> Where "..." may be any specialisation-specific code, e.g. an
> eval that recreates some methods in a speed-optimised way
> depending on t.
>
> Does that make sense?
>
> However I have no experience combining regular inheritance
> and this technique, and I know this technique may be
> difficult to combine with regular inheritance in a way that
> makes it really closer to C++.

Your technique already combines regular inheritance - all of your A.of(t)
classes inherit from A, so any method defined in A will be inherited by
A.of(t). My question (and Robert gave a good answer on how to do this) was
one degree more complicated because I not only wanted the child classes to
have their own implementation but wanted any classes that inherit from
*them* to have their own implementation as well.

> Btw, what's the class A<<MyBaseClass syntax? AFAIK it's
> either class A<MyBaseClass or class<<A. Is this a new syntax?

Heh, that's just air coding gone bad. << is not used for inheritance in
Ruby (AFAIK).

Adelle.



Adelle Hartley

3/26/2005 10:29:00 AM

0

ARggh.

> > > module Extension
> > > # this one is really only neede if you
> > > # want to inherit this behavior automatically
> > > # down the class hierarchy
> > > def inherited(cl)
> > > cl.extend Extension
> > > end

This is pretty neat if I want to add class methods to child classes. Is
their an equivalent mechanism for adding instance methods?

Adelle.



Robert Klemme

3/26/2005 5:22:00 PM

0


"Adelle Hartley" <adelle@bullet.net.au> schrieb im Newsbeitrag
news:courier.42453960.00006AA7@mars.sisgroup.com.au...
> ARggh.
>
>> > > module Extension
>> > > # this one is really only neede if you
>> > > # want to inherit this behavior automatically
>> > > # down the class hierarchy
>> > > def inherited(cl)
>> > > cl.extend Extension
>> > > end
>
> This is pretty neat if I want to add class methods to child classes. Is
> their an equivalent mechanism for adding instance methods?

Not needed as they are inherited if you use "normal" module inclusion:

>> module Foo; def bar() "bar" end end
=> nil
>> class A
>> include Foo
>> end
=> A
>> class B < A
>> end
=> nil
>> B.new.bar
=> "bar"

Cheers

robert