tupleof for inherited classes.

Chris NS ibisbasenji at gmail.com
Wed Jul 25 01:03:39 PDT 2012


I know you specifically asked for a way to do this without 
templates, but this was my first thought on how to make it work 
(and I confirmed it):

##############################
import  std.stdio   ,
         std.traits  ;

class Engine {

     int publicField ;

     void enumFields ( this Self ) ( bool heading = true ) {
         auto self = cast( Self ) this;
         if ( heading ) {
             writeln( "Engine prints:" );
         }
         foreach( base ; BaseClassesTuple!Self ) {
             static if ( is( base : Engine ) ) {
                 ( cast( base ) self ).enumFields( false );
             }
         }
         foreach( ref field ; self.tupleof ) {
             writeln( '\t', field );
         }
     }

     protected string protectedField = "s" ;

     private bool privateField ;

}

class Some : Engine {

     int oneMoreField = 11;

     void enumFields2 () {
         writeln( "Some prints:" );
         foreach( field ; this.tupleof ) {
             writeln( '\t', field );
         }
     }

     protected string protectedField = "o";

}

void main () {
     auto objE = new Engine;
     auto objS = new Some;

     objE.enumFields();

     objS.publicField = 4;
     objS.enumFields();
     objS.enumFields2();

     ( cast( Engine ) objS ).enumFields();
}
##############################

The downside is that the reference you invoke enumFields() 
against must be of the lowest type to get all members, as that 
last line demonstrates.  Beyond this, I don't believe there is 
any way for methods defined by Engine to see members of derived 
classes.  The first alternative I could think of, is to use NVI 
(non-virtual interfaces).

##############################
import  std.stdio   ;

class Engine {

     int publicField ;

     final void enumFields () {
         writeln( this.classinfo.name, " prints:" );
         enumFieldsImpl();
     }

     protected string protectedField = "s" ;

     protected void enumFieldsImpl () {
         foreach ( field ; this.tupleof ) {
             writeln( '\t', field );
         }
     }

     private bool privateField ;

}

class Some : Engine {

     int oneMoreField = 11;

     protected override void enumFieldsImpl () {
         super.enumFieldsImpl();
         foreach ( field ; this.tupleof ) {
             writeln( '\t', field );
         }
     }

     protected string protectedField = "o";

}

void main () {
     auto objE = new Engine;
     auto objS = new Some;

     objE.enumFields();

     objS.publicField = 4;
     objS.enumFields();

     ( cast( Engine ) objS ).enumFields();
}
##############################

This works even in the last (previously degenerate) case, however 
it naturally results in code duplication.  Depending on what your 
real scenario is, however, that may not be a severe issue.

-- Chris NS


More information about the Digitalmars-d-learn mailing list