Instead of templates

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.

"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

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"

I don't claim to represent the "Ruby Way", but personally I've done
similar things (in the RubyX11 project) that implement
parametrized-classes this way:

In each parametrized class, make a (class-wide) hash, and then create new
subclasses on-demand, remembering them in that hash. Then I may allow a
syntax like:

  List.of(Float)

or

  List[Float]

... as typenames, which get associated with an anonymous class that
subclasses my baseclass.

e.g.:

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

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++.

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

···

On Thu, 24 Mar 2005, Adelle Hartley wrote:

  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?

_____________________________________________________________________
Mathieu Bouchard -=- Montréal QC Canada -=- http://artengine.ca/matju

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.

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" <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

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.

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.

"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