Inheritance, mixins and initializers

Hi,

I've got a question regarding inheritance, mixins, order of initialization
and calling module/super class "initializers". I'd like to do something
along the lines of (pseudo-ruby code):

···

---
class Base
    def initialize(field_count)
        @fields = Array.new(field_count)
    end
end

module FooMixin
    def initialize(foo_field)
        @foo_field = foo_field
        self.fields[@foo_field] = Foo.new
    end

    def foo
        self.fields[@foo_field]
    end
end

module BarMixin
    def initialize(bar_field)
        @bar_field = bar_field
        self.fields[@bar_field] = Bar.new
    end

    def bar
        self.fields[@bar_field]
    end
end

class Derived < Base
    include FooMixin
    include BarMixin
    def initialize
        super(2)
        FooMixin(0)
        BarMixin(1)
    end
end

---

Obviously this doesn't work - is there any way of achieving something
similar? The Foo/Bar mixins depend on Base being initialized before them
(ok, maybe not in this particular example).

// Johan

"Johan Nilsson" <johan.nilsson@---.esrange.ssc.se> schrieb im Newsbeitrag
news:1102594375.344eddcc1c357ac539046c764cd8c6b8@teranews...

Hi,

I've got a question regarding inheritance, mixins, order of

initialization

and calling module/super class "initializers". I'd like to do something
along the lines of (pseudo-ruby code):

---
class Base
    def initialize(field_count)
        @fields = Array.new(field_count)
    end
end

module FooMixin
    def initialize(foo_field)
        @foo_field = foo_field
        self.fields[@foo_field] = Foo.new
    end

    def foo
        self.fields[@foo_field]
    end
end

module BarMixin
    def initialize(bar_field)
        @bar_field = bar_field
        self.fields[@bar_field] = Bar.new
    end

    def bar
        self.fields[@bar_field]
    end
end

class Derived < Base
    include FooMixin
    include BarMixin
    def initialize
        super(2)
        FooMixin(0)
        BarMixin(1)
    end
end

---

Obviously this doesn't work - is there any way of achieving something
similar? The Foo/Bar mixins depend on Base being initialized before them
(ok, maybe not in this particular example).

I don't know which real problem you are trying to solve. I can think of
several other approaches. You might want to store your mixin created
instances directly in instance variables and record only the names of
these.

class Foo;end
class Bar;end

class Base
    attr_reader :fields
    def initialize()
        @fields =
    end

    def add_field(name) @fields << name end
    def all_fields() @fields.map {|f| instance_variable_get f} end
end

module FooMixin
    attr_reader :foo

    def initialize(*a,&b)
        super
        @foo = Foo.new
        add_field "@foo"
    end
end

module BarMixin
    attr_reader :bar

    def initialize(*a,&b)
        super
        @bar = Bar.new
        add_field "@bar"
    end
end

class Derived < Base
    include FooMixin
    include BarMixin
    def initialize
      super
    end
end

Or you can determine the position automatically.

class Foo;end
class Bar;end

class Base
    attr_reader :fields
    def initialize()
        @fields =
    end
end

module FooMixin
    def initialize(*a,&b)
        super
        @foo_field = self.fields.size
        self.fields << Foo.new
    end

    def foo
        self.fields[@foo_field]
    end
end

module BarMixin
    def initialize(*a,&b)
        super
        @bar_field = self.fields.size
        self.fields << Bar.new
    end

    def bar
        self.fields[@bar_field]
    end
end

class Derived < Base
    include FooMixin
    include BarMixin
    def initialize
      super
    end
end

Kind regards

    robert

"Robert Klemme" <bob.news@gmx.net> schrieb im Newsbeitrag
news:31qukrF3d6rb9U1@individual.net...

"Johan Nilsson" <johan.nilsson@---.esrange.ssc.se> schrieb im

Newsbeitrag

news:1102594375.344eddcc1c357ac539046c764cd8c6b8@teranews...
> Hi,
>
> I've got a question regarding inheritance, mixins, order of
initialization
> and calling module/super class "initializers". I'd like to do

something

> along the lines of (pseudo-ruby code):

<snip/>

Here's another solution - even more general:

class Foo;end
class Bar;end
class Baz;end

module FieldMixin
  def fields(*classes)
    classes.each do |cl|
      attr_reader cl.name.downcase.to_sym
    end

    define_method(:initialize) do
      super()
      classes.each do |cl|
        instance_variable_set( "@#{cl.name.downcase}", cl.new )
      end
    end
  end

  def inherited(cl) cl.extend FieldMixin end
end

class Base
  extend FieldMixin
end

class Derived < Base
  fields Foo, Bar
end

class Der2 < Derived
  fields Baz
end

Derived.new.foo
Derived.new.bar
Der2.new.foo
Der2.new.baz

Kind regards

    robert

"Robert Klemme" <bob.news@gmx.net> wrote in message
news:31qukrF3d6rb9U1@individual.net...

"Johan Nilsson" <johan.nilsson@---.esrange.ssc.se> schrieb im Newsbeitrag
news:1102594375.344eddcc1c357ac539046c764cd8c6b8@teranews...
> Hi,
>
> I've got a question regarding inheritance, mixins, order of
initialization
> and calling module/super class "initializers". I'd like to do something
> along the lines of (pseudo-ruby code):
>

[snip]

I don't know which real problem you are trying to solve. I can think of
several other approaches. You might want to store your mixin created
instances directly in instance variables and record only the names of
these.

Thanks for your reply(s), I'll check them out.

I'm actually mapping a legacy C++ construct to Ruby (no, this is not the
actual code and probably contain some typos):

···

---
struct FooBarBase {};
struct Foo : FooBarBase {};
struct Bar : FooBarBase {};

class Base
{
protected:
    Base(int stuffs)
        : m_stuff(stuffs, boost::shared_ptr<FooBarBase>())
    {}
    void add_stuff_at(int index, boost::shared_ptr<FooBarBase> pfb)
    { m_stuff.at(index) = pfb; }

public:
    ... functions operating on all "stuff" as a homogenous collection ...
private:
    std::vector<boost::shared_ptr<FooBarBase> > m_stuff;
};

template<typename Mixee, int which>
struct FooMixin
{
    FooMixin()
        : m_pFoo(boost::shared_ptr<Foo>(new Foo))
    { return static_cast<Mixee*>(this)->add_stuff_at(which, m_pFoo); }

    const Foo& foo() const
    { return *m_pFoo; }
private:
    boost::shared_ptr<Foo> m_pFoo;
};

template<typename Mixee, int which>
struct BarMixin
{ ... };

struct Derived
    : Base
    , FooMixin<Derived, 0>
    , BarMixin<Derived, 1>
{
    Derived()
      : Base(2)
    {}
};

int main(int, char*)
{
    Derived d;
    const Foo& foo = d.foo();
    d.bar();
    return 0;
}

---

To further complicate matters I was trying to use SWIG to inherit from the
C++ class "Base" using the cross-language polymorhism feature. Now I believe
I'll rewrite this part in Ruby instead (but the FooBaseBase stuff etc will
still be wrapped from C++).

Thanks again

// Johan

"Johan Nilsson" <johan.nilsson@---.esrange.ssc.se> schrieb im Newsbeitrag
news:1102597896.fbf426538d0cb3bf826331d7f2d41e34@teranews...

"Robert Klemme" <bob.news@gmx.net> wrote in message
news:31qukrF3d6rb9U1@individual.net...
>
> "Johan Nilsson" <johan.nilsson@---.esrange.ssc.se> schrieb im

Newsbeitrag

> news:1102594375.344eddcc1c357ac539046c764cd8c6b8@teranews...
> > Hi,
> >
> > I've got a question regarding inheritance, mixins, order of
> initialization
> > and calling module/super class "initializers". I'd like to do

something

> > along the lines of (pseudo-ruby code):
> >
[snip]

>
> I don't know which real problem you are trying to solve. I can think

of

> several other approaches. You might want to store your mixin created
> instances directly in instance variables and record only the names of
> these.

Thanks for your reply(s), I'll check them out.

I'm actually mapping a legacy C++ construct to Ruby (no, this is not the
actual code and probably contain some typos):

---
struct FooBarBase {};
struct Foo : FooBarBase {};
struct Bar : FooBarBase {};

class Base
{
protected:
    Base(int stuffs)
        : m_stuff(stuffs, boost::shared_ptr<FooBarBase>())
    {}
    void add_stuff_at(int index, boost::shared_ptr<FooBarBase> pfb)
    { m_stuff.at(index) = pfb; }

public:
    ... functions operating on all "stuff" as a homogenous collection

....

private:
    std::vector<boost::shared_ptr<FooBarBase> > m_stuff;
};

template<typename Mixee, int which>
struct FooMixin
{
    FooMixin()
        : m_pFoo(boost::shared_ptr<Foo>(new Foo))
    { return static_cast<Mixee*>(this)->add_stuff_at(which, m_pFoo); }

    const Foo& foo() const
    { return *m_pFoo; }
private:
    boost::shared_ptr<Foo> m_pFoo;
};

template<typename Mixee, int which>
struct BarMixin
{ ... };

struct Derived
    : Base
    , FooMixin<Derived, 0>
    , BarMixin<Derived, 1>
{
    Derived()
      : Base(2)
    {}
};

int main(int, char*)
{
    Derived d;
    const Foo& foo = d.foo();
    d.bar();
    return 0;
}

---

To further complicate matters I was trying to use SWIG to inherit from

the

C++ class "Base" using the cross-language polymorhism feature. Now I

believe

I'll rewrite this part in Ruby instead (but the FooBaseBase stuff etc

will

still be wrapped from C++).

This sounds awfully complicated. Good luck!

Thanks again

You're welcome!

Kind regards

    robert

"Robert Klemme" <bob.news@gmx.net> wrote in message
news:31qvkoF3f29i9U1@individual.net...

[snip]

class Derived < Base
  fields Foo, Bar
end

That's most elegant (the "fields Foo, Bar" stuff). I still need to be able
to access the fields by index as well as to name the fields (could be more
than one of a kind), but I think I can manage that by myself.

Thanks,

Johan