Get symbols (and/or UDAs) of subclass from superclass

Basile B. b3.temp at gmx.com
Sun Mar 15 22:19:55 UTC 2020


On Sunday, 15 March 2020 at 20:18:03 UTC, James Blachly wrote:
> I would like to programmatically retrieve members of a subclass 
> to create a self-documenting interface. I am afraid that my 
> approach is not possible due to need for compile time __traits 
> / std.traits, and runtime typeinfo. My proposed approach is as 
> follows:
>
> class Base
> {
>     string whatever;
>
>     string toString()
>     {
>         // loop over __traits(allMembers, typeof(this)) or 
> getSymbolsByUDA, etc.
>     }
> }
>
> /// There may be a dozen Derived classes
> class Derived1 : Base
> {
>     @Config("a name", "a description")
>     float probability;
> }
> class Derived2 : Base
> {
>     @Config("another", "more description")
>     int replicates;
> }
> ...
>
> Unfortunately, I am afraid this doesn't look possible because 
> of the need for compile-time UDAs and runtime TypeInfo. Is 
> there a way to do this without re-implementing toString in 
> every single derived class? I expect there to be many derived 
> classes.
>
> Other ideas welcomed, as I usually write C-style D and am only 
> recently taking a stab at OO Inheritance features.
>
> Thanks in advance.
> James

A few years ago I've been faced to a similar problem and I ended 
up by using an array, defined in the base class which was filled 
by "hybdrid" runtime/compile-time reflection (explanations about 
this come later).

In each derived class the constructor performed reflection, using 
__traits(derivedMembers) + UDA filtering and the array from the 
base class received the new stuff...

More concrectly:

---
class Base
{
     Stuff[] stuff;
}

/// There may be a dozen Derived classes
class Derived1 : Base
{
     @Config("a name", "a description")
     float probability;

     this()
     {
         foreach(dm; __traits(derivedMembers, this))
         { /* UDA filtering, then add to stuff*/ }
     }

}
class Derived2 : Base
{
     @Config("another", "more description")
     int replicates;

     this()
     {
         foreach(dm; __traits(derivedMembers, this))
         { /* UDA filtering, then add to stuff*/ }
     }
}
---

This worked and would work for you but you'll be faced to several 
issues, for example the most obvious is what is the type of 
Stuff...

Another, less immediate, is that because of overridden methods 
some already existing entries in the array of Stuff may have to 
be replaced.

Oterwise the thing to get here is that altough you use 
compile-time reflection, the reflection code is only executed at 
runtime, to fill the array of Stuff.


More information about the Digitalmars-d-learn mailing list