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