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