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?
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.