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

2020-03-16 Thread James Blachly via Digitalmars-d-learn

On 3/15/20 5:28 PM, Simen Kjærås wrote:
...
Since toStringImpl will always call toStringBase, this could perhaps 
better be modeled with a template mixin:


mixin template DerivedToString() {
     override string toStringImpl() {
     return this.toStringBase();
     }
}

class Derived2 : Base {
     mixin DerivedToString!();
}

This way, you can have all the logic of toString in the base class, and 
the only thing a subclass will have to include is one line for the 
mixin. In addition, since toStringImpl is abstract, the implementer of a 
subclass will get a compile-time error if he or she forgets to do either 
the mixin or override toStringImpl themselves.


--
   Simen


Thanks to you and Basile for responses and distinct solutions to 
consider. I am working on the mixin approach now, but with a brief 
mixinline in each derived subclass, I do not even need to call a 
superclass method -- just write the display code once with UDA 
filtering. I think this is the most sensible approach, until something 
else unexpected comes up :)


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

2020-03-15 Thread Basile B. via Digitalmars-d-learn

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.


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

2020-03-15 Thread Simen Kjærås via Digitalmars-d-learn

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;
}
...


There's no built-in way to do this - toString() doesn't know what 
derived classes exist, and more could be added from other modules 
and even dynamically loaded libraries. Now, there are ways to do 
something somewhat like it. I would suggest creating an abstract 
method in the base class, that derived class would have to 
override, and use a template this argument to get the correct 
type for __traits(allMembers) to operate on:


class Base {
override string toString() {
return toStringImpl();
}
abstract string toStringImpl();
string toStringBase(this That)() {
// foreach (e; __traits(allMembers, That) {...}
}
}

class Derived : Base {
override string toStringImpl() {
return this.toStringBase();
}
}

Since toStringImpl will always call toStringBase, this could 
perhaps better be modeled with a template mixin:


mixin template DerivedToString() {
override string toStringImpl() {
return this.toStringBase();
}
}

class Derived2 : Base {
mixin DerivedToString!();
}

This way, you can have all the logic of toString in the base 
class, and the only thing a subclass will have to include is one 
line for the mixin. In addition, since toStringImpl is abstract, 
the implementer of a subclass will get a compile-time error if he 
or she forgets to do either the mixin or override toStringImpl 
themselves.


--
  Simen


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

2020-03-15 Thread James Blachly via Digitalmars-d-learn
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