www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Idiomatic way to call base method in generic code

reply "ZombineDev" <valid_email he.re> writes:
import std.stdio, std.conv, std.traits;

class Base
{
     int x;
     override string toString() const
     {
         return x.to!string;
     }
}

class Derived : Base
{
     int y;
     override string toString() const
     {
         return y.to!string;
     }
}

void callMethod(T, alias Method)(const T thiz)
{
     thiz.fun();
}

void callBaseMethod(SubClass, alias Method)(const SubClass thiz)
{
     alias FirstSuperClass = BaseClassesTuple!(SubClass)[0];
     thiz.FirstSuperClass.Method();
}

void main()
{
     Derived d = new Derived();
     d.y = 15; d.x = 13;

     // 1) callMethod!(Derived, Derived.toString)(d);
     // 2) callBaseMethod!(Derived, Derived.toString)(d);
     // 3) writeln(d.Base.toString());

}


I know I can call a base implementation of a method like in 3), 
but I need to do it generically like in 2). Does anybody now how 
I can achieve this?
Additionally is there a way to make 1) work without using string 
mixins?
May 24 2015
next sibling parent "ZombineDev" <valid_email he.re> writes:
On Sunday, 24 May 2015 at 23:32:52 UTC, ZombineDev wrote:
 ...
Small correction for clarity: void main() { Derived d = new Derived(); d.x = 13; d.y = 15; // 1) writeln(callMethod!(Derived, Derived.toString)(d)); <- Should print 15 // 2) writeln(callBaseMethod!(Derived, Derived.toString)(d)); <- Should print 13 // 3) writeln(d.Base.toString()); <- Prints 13 }
May 24 2015
prev sibling parent reply ketmar <ketmar ketmar.no-ip.org> writes:
On Sun, 24 May 2015 23:32:50 +0000, ZombineDev wrote:

 I know I can call a base implementation of a method like in 3), but I
 need to do it generically like in 2). Does anybody now how I can achieve
 this?
i don't know why you want that, but something like this may do: auto callBaseMethod(string MTN, C, Args...) (inout C self, Args args) { alias FSC =3D BaseClassesTuple!(C)[0]; return mixin(`self.`~FSC.stringof~`.`~MTN~"(args)"); } writeln(d.callBaseMethod!"toString");
 Additionally is there a way to make 1) work without using string mixins?
no. and again, why do you want that? why do you people are so afraid of=20 string mixins? ;-)=
May 25 2015
parent reply "ZombineDev" <valid_email he.re> writes:
On Monday, 25 May 2015 at 07:57:49 UTC, ketmar wrote:
 i don't know why you want that, but something like this may do:

 auto callBaseMethod(string MTN, C, Args...) (inout C self, Args 
 args) {
   alias FSC = BaseClassesTuple!(C)[0];
   return mixin(`self.`~FSC.stringof~`.`~MTN~"(args)");
 }

 writeln(d.callBaseMethod!"toString");
Thanks! [1]: https://github.com/ZombineDev/Chess2RT/blob/c36ba3e73744cf3912c25abccedbbd742f7f5be3/source/util/prettyprint.d#L7 [2]: https://github.com/ZombineDev/Chess2RT/blob/master/source/util/prettyprint.d#L14 I initially had [1] a string mixin which goes through all the members of a class and prints them and also prints its base class' members, but then it seemed that it would be more cleaner if I could use a function template [2] (which also improved my debug experience) so I started exploring alias, but they turned out to be less powerful then I thought: alias can't refer to a nested member: ------------- struct Point2 { float x; float y; } struct Line2 { Point2 start; Point2 end; mixin Access; // alias x1 = this.start.x; <- this doesn't work :( alias x1 = get!"start.x"; alias y1 = get!"start.y"; alias x2 = get!"end.x"; alias y2 = get!"end.y"; } // I need to use a mixin to flatten the access :( private mixin template Access() { ref auto get(string accessPattern)() inout { return mixin(accessPattern); } } ------------- So I wondered if I'm missing something and decided to ask here.
 no. and again, why do you want that? why do you people are so 
 afraid of
 string mixins? ;-)
Well I'm not afraid of string mixins, but the `alias` keyword seemed to possess some mysterious power (I was also under the influence of this [3] blog post) which I wanted to explore. Also they're a bit more elegant. [3]: http://blog.thecybershadow.net/2015/04/28/the-amazing-template-that-does-nothing/
May 25 2015
next sibling parent "Meta" <jared771 gmail.com> writes:
On Monday, 25 May 2015 at 09:24:58 UTC, ZombineDev wrote:
 On Monday, 25 May 2015 at 07:57:49 UTC, ketmar wrote:
 i don't know why you want that, but something like this may do:

 auto callBaseMethod(string MTN, C, Args...) (inout C self, 
 Args args) {
  alias FSC = BaseClassesTuple!(C)[0];
  return mixin(`self.`~FSC.stringof~`.`~MTN~"(args)");
 }

 writeln(d.callBaseMethod!"toString");
Thanks! [1]: https://github.com/ZombineDev/Chess2RT/blob/c36ba3e73744cf3912c25abccedbbd742f7f5be3/source/util/prettyprint.d#L7 [2]: https://github.com/ZombineDev/Chess2RT/blob/master/source/util/prettyprint.d#L14 I initially had [1] a string mixin which goes through all the members of a class and prints them and also prints its base class' members, but then it seemed that it would be more cleaner if I could use a function template [2] (which also improved my debug experience) so I started exploring alias, but they turned out to be less powerful then I thought: alias can't refer to a nested member: ------------- struct Point2 { float x; float y; } struct Line2 { Point2 start; Point2 end; mixin Access; // alias x1 = this.start.x; <- this doesn't work :( alias x1 = get!"start.x"; alias y1 = get!"start.y"; alias x2 = get!"end.x"; alias y2 = get!"end.y"; } // I need to use a mixin to flatten the access :( private mixin template Access() { ref auto get(string accessPattern)() inout { return mixin(accessPattern); } } ------------- So I wondered if I'm missing something and decided to ask here.
 no. and again, why do you want that? why do you people are so 
 afraid of
 string mixins? ;-)
Well I'm not afraid of string mixins, but the `alias` keyword seemed to possess some mysterious power (I was also under the influence of this [3] blog post) which I wanted to explore. Also they're a bit more elegant. [3]: http://blog.thecybershadow.net/2015/04/28/the-amazing-template-that-does-nothing/
You might be interested in this thread: http://forum.dlang.org/thread/mi3pip$22va$1 digitalmars.com
May 25 2015
prev sibling next sibling parent ketmar <ketmar ketmar.no-ip.org> writes:
On Mon, 25 May 2015 09:24:56 +0000, ZombineDev wrote:

 On Monday, 25 May 2015 at 07:57:49 UTC, ketmar wrote:
 i don't know why you want that, but something like this may do:

 auto callBaseMethod(string MTN, C, Args...) (inout C self, Args args) {
   alias FSC =3D BaseClassesTuple!(C)[0];
   return mixin(`self.`~FSC.stringof~`.`~MTN~"(args)");
 }

 writeln(d.callBaseMethod!"toString");
Thanks!
note that this funny trick works even for `void` methods, due to magic of=20 `auto` return type.=
May 25 2015
prev sibling parent ketmar <ketmar ketmar.no-ip.org> writes:
On Mon, 25 May 2015 09:24:56 +0000, ZombineDev wrote:

 alias can't refer to a nested member:
 -------------
 struct Point2 {
      float x;
      float y;
 }
=20
 struct Line2 {
      Point2 start;
      Point2 end;
=20
      mixin Access;
=20
      // alias x1 =3D this.start.x; <- this doesn't work :(
=20
      alias x1 =3D get!"start.x";
      alias y1 =3D get!"start.y";
      alias x2 =3D get!"end.x";
      alias y2 =3D get!"end.y";
 }
=20
 // I need to use a mixin to flatten the access :(
 private mixin template Access()
 {
      ref auto get(string accessPattern)() inout {
          return mixin(accessPattern);
      }
 }
 -------------
i wonder if there is a reason for that limitation (except "nobody=20 implemented that feature yet", of course).=
May 25 2015