Search code examples
d

Is there a way to specify which function to override?


interface A
{
    void f();
}
interface B
{
    void f();
}
class C : A ,B
{
// pseudocode 
    void A::a(){}
    void B::a(){}
}

Is there a way to have different implementations of A::f and B::f in the same class?


Solution

  • When they both have the same signature, no*. If A.f is void f() and B.f is int f(), it's possible.

    * actually, there is a way, if you accept that it's not doing exactly the same thing:

    interface A { string f(); }
    
    interface B { string f(); }
    
    class C : A {
        string f() { return "A"; }
        string bf() { return "B"; }
        
        // Pretend to be a B
        alias get this;
        B get() {
            auto that = this;
            return new class B {
                string f() { return that.bf(); }
            };
        }
    }
    
    unittest {
        auto c = new C();
        
        A a = c;
        B b = c;
        
        assert(a.f() == "A");
        assert(b.f() == "B");
    }
    

    In the above code, we are using alias this to create a kind of second inheritance chain. There are some problems with this, the biggest that we can't cast from the thing returned from get() back to C.

    This could be made more generic with UDAs and a mixin, such that this should compile and run:

    interface A { string f(); }
    interface B { string f(); }
    interface C { string f(); }
    @implements!(B, C)
    class D : A {
        string f() { return "A"; }
        @implements!(B.f)
        string bf() { return "B"; }
        @implements!(C.f)
        string cf() { return "C"; }
        mixin implement!();
    }
    
    unittest {
        D d = new D();
        A a = d;
        B b = d;
        C c = d;
    
        assert(a.f() == "A");
        assert(b.f() == "B");
        assert(c.f() == "C");
    
        assert(a == cast(A)d);
        assert(b == cast(B)d);
        assert(c == cast(C)d);
    }
    

    That, however, is left as an exercise for the reader.