Jarrett Billingsley wrote:
On Thu, Oct 1, 2009 at 12:25 PM, Andrei Alexandrescu
<seewebsiteforem...@erdani.org> wrote:
[code injection]
What do you think?

I think it sounds interesting enough, but I can't help but wonder if
this is a feature that you've really thought through (especially wrt.
how it interacts with mechanisms such as template mixins and normal
symbol inheritance), or if you just want it to support some pattern
you want to use in Phobos 2.

I've known for a long time this was in store if we want to define decent reflection. It's also been a perennial source of trouble with a lot of code that needs to inject members.

Let me give another example. When we discussed opCmp around here, people said that's the old way of doing things and that the right way is to use an interface Comparator!T, akin to Java's Comparator<T>:

http://java.sun.com/j2se/1.5.0/docs/api/java/util/Comparator.html

That only solves exactly one level of inheritance. It's a more elaborate solution that doesn't quite help that much. Consider:

interface Comparator(T)
{
    int opCmp(T rhs); // yum, exact type
}

class Widget : Comparator!Widget
{
    override opCmp(Widget rhs) { ... } // yum, exact type
}

class Gadget : Widget
{
    override opCmp(Gadget rhs) { ... } // ERROR!!!!!!!!
}

Of course that didn't work. Gadget.opCmp doesn't override anything. Gadget needs to remember to inherit Comparator!Gadget:

class Gadget : Widget, Comparator!Gadget
{
    override opCmp(Gadget rhs) { ... } // oh ok
}

So any class X in Widget's hierarchy that forgets to inherit Comparator!X undergoes the risk of having the wrong opCmp called for it.

With injection, Comparator can be made to work for any interface:

interface Comparator(T)
{
    int opCmp(Comparator!T rhs);
    mixin(Impl) // for each implementation Impl
    {
        int opCmp(Impl rhs);
        override int opCmp(Comparator!T rhs)
        {
            return opCmp(cast(Impl) rhs);
        }
    }
}

class Widget : Comparator!Widget { ... }

Now every derived class of Widget, including Widget itself, commits to define a opCmp with the proper signature (failure to do so results in a linker error), and also defines the interface function in terms of it.


Andrei

Reply via email to