On Thursday, 28 April 2016 at 10:21:34 UTC, Andrew Benton wrote:
I'm running into a set of problems where both inheritance and mixin-added functionality really lend a hand to my project. Unfortunately, they don't necessarily work well together, as certain mixins need to be restated for each inheritor.

As a toy example, if I wanted to mixin some functionality to write names:

mixin template WriteName()
{
    string writeName()
    {
        import std.uuid : randomUUID;
        static if(__traits(hasMember, this, "name"))
            return __traits(getMember, this, "name);
        else
            return randomUUID.toString;
    }
}
class Base
{
    mixin WriteName;
}
class Inheritor : Base
{
    version(both) mixin WriteName;
    string name = "test";
}

In the above example, unless I used version "both", I would see only random UUIDs from instances of Base and Inheritor, however the functionality that I really want is to get random UUIDs only from Base, and get "test" from Inheritor. So far as I know, the easiest way to fix this is to add that mixin to each descendant of Base.

I recognize that, at least for this toy example, an easier fix is to use a templated function, however I'm more interested in libraries like jsonizer and witchcraft.

So to the point: Is there an easier way to do this that I'm missing? Is there a language-design reason that mixed in templates can't inherit? It seems like an intuitive use of mixin.

This is a common error with mixin template. The static things gets only evaluated once. If you want to be evaluated in each class type you need a true template that get an instance in each class. However the method then **wont be virtual** !!

----
mixin template WriteName()
{
    string writeName(this T)()
    {
        import std.uuid : randomUUID;
        static if (__traits(hasMember, T, "name"))
            return __traits(getMember, cast(T)this, "name");
        else
            return randomUUID.toString;
    }
}
class Base
{
    mixin WriteName;
}
class Inheritor : Base
{
    string name = "test";
}

void main()
{
    import std.stdio;
    writeln((new Base).writeName!Base); // an UUID
    writeln((new Inheritor).writeName!Inheritor); // test
}
----

see template this parameter:

https://dlang.org/spec/template.html#TemplateThisParameter

Reply via email to