digitalmars.D.learn - Multiple Inheritance, Mixins, and Constructors
- Chris Williams (38/38) May 18 2009 Well so I had a case where I needed to do something like multiple inheri...
- Ary Borenszweig (21/70) May 18 2009 You can do this:
- Chris Williams (4/28) May 19 2009 Well I ended up converting my object to a struct, which solved the issue...
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
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
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