www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Multiple Inheritance, Mixins, and Constructors

reply Chris Williams <littleratblue yahoo.co.jp> writes:
Well so I had a case where I needed to do something like multiple inheritance.
Here's an example solution:

interface IFoo {
   void bar();
}
template TFoo() {
   void bar() {
      // code
      // ...
   }
}

class Base {
   // variables
}

class Thing : Base, IFoo {
   mixin TFoo;
}

Well so that's all well and good. The problem comes if I have an object
declared in TFoo. For instance:

template TFoo() {
   SomeObject s_o;

   void bar() {
      s_o.x = 10;
      
      // code
      // ...
   }
}

It compiles fine, but when I go to run it, trying to set so.x gets an error
because s_o hasn't been instantiated. If I try:

template TFoo() {
   SomeObject s_o = new SomeObject();

   void bar() {
      s_o.x = 10;
      
      // code
      // ...
   }
}

Then I get a compile-time error that I can't do that. Now I'd love to define a
constructor in TFoo that instantiated s_o, but I'm pretty sure that would
conflict should anyone try to add a constructor to (for instance) class Thing.

My solution was to add an initFoo() definition in IFoo, and say that it needs
to be called in the constructor of anyone using IFoo/TFoo, but that seems
pretty wonky. Admittedly the whole interface/mixin thing is already a bit
wonky, but it seems like there should be a solution to at least the object
initialization problem.
May 18 2009
parent reply Ary Borenszweig <ary esperanto.org.ar> writes:
Chris Williams escribió:
 Well so I had a case where I needed to do something like multiple inheritance.
Here's an example solution:
 
 interface IFoo {
    void bar();
 }
 template TFoo() {
    void bar() {
       // code
       // ...
    }
 }
 
 class Base {
    // variables
 }
 
 class Thing : Base, IFoo {
    mixin TFoo;
 }
 
 Well so that's all well and good. The problem comes if I have an object
declared in TFoo. For instance:
 
 template TFoo() {
    SomeObject s_o;
 
    void bar() {
       s_o.x = 10;
       
       // code
       // ...
    }
 }
 
 It compiles fine, but when I go to run it, trying to set so.x gets an error
because s_o hasn't been instantiated. If I try:
 
 template TFoo() {
    SomeObject s_o = new SomeObject();
 
    void bar() {
       s_o.x = 10;
       
       // code
       // ...
    }
 }
 
 Then I get a compile-time error that I can't do that. Now I'd love to define a
constructor in TFoo that instantiated s_o, but I'm pretty sure that would
conflict should anyone try to add a constructor to (for instance) class Thing.
 
 My solution was to add an initFoo() definition in IFoo, and say that it needs
to be called in the constructor of anyone using IFoo/TFoo, but that seems
pretty wonky. Admittedly the whole interface/mixin thing is already a bit
wonky, but it seems like there should be a solution to at least the object
initialization problem.
You can do this: template TFoo() { // Never use this variable directly :-P SomeObject _s_o; SomeObject s_o() { if (_s_o is null) _s_o = new SomeObject(); return _s_o; } // And if you want to make it assignable too SomeObject s_o(SomeObject x) { _s_o = x; } void bar() { s_o.x = 10; // code // ... } }
May 18 2009
parent Chris Williams <littleratblue yahoo.co.jp> writes:
Ary Borenszweig Wrote:

 
 You can do this:
 
 template TFoo() {
 	// Never use this variable directly :-P
 	SomeObject _s_o;
 
 	SomeObject s_o() {
 		if (_s_o is null)
 			_s_o = new SomeObject();
 		return _s_o;
 	}
 
 	// And if you want to make it assignable too
 	SomeObject s_o(SomeObject x) {
 		_s_o = x;
 	}
 	
 	void bar() {
 		s_o.x = 10;
 		// code
 		// ...
 	}
 }
Well I ended up converting my object to a struct, which solved the issue. Your solution would probably work, but for what I'm doing, I'd rather not incur the overhead of a branch and (possible) function call for every access of the object. It seems like object initialization outside of a method should be magically moved to the top of the constructor. But ah well. Thank you.
May 19 2009