On Thursday, 23 July 2015 at 15:20:36 UTC, jmh530 wrote:
It definitely seems weird that this behavior isn't
mentioned anywhere.

It isn't really expanded upon, but the : Interfaces at the top here tells you can inherit them:

http://dlang.org/interface.html

It doesn't show an example in the text of an interface extending another interface, but it does say "interfaces can be inherited".

Also, the use of static* or final methods in the interface can allow default implementations of methods.

Eh sort of but not really. static and final methods cannot be overridden in the virtual sense.

interface Foo {
        final void foo() { writeln("foo"); }
}
class Bar : Foo {
        override void foo() { writeln("foo from bar"); }
}


b.d(8): Error: function b.Bar.foo does not override any function, did you mean
o override 'b.Foo.foo'?
b.d(8): Error: function b.Bar.foo cannot override final function Foo.b.Foo.foo



Static is similar, change those finals to static and you get:


b.d(8): Error: function b.Bar.foo cannot override a non-virtual function


Take override off and it compiles... but is statically dispatched:

        Foo bar = new Bar();
        bar.foo(); // calls the version from the interface

        Bar bar = new Bar();
        bar.foo(); // calls the version from the class



That's the main thing with interfaces: you are supposed to get the overridden method when you call it through the base, but that only happens if it is virtual - neither final nor static. And those cannot have default implementations in a D interface, only in a class.

The tricky part is that I had been using something like final foo() { } instead of final void foo() { }. For some reason you can override the first, but not the second.


You just defined a template by skipping the return type... templates are allowed in D interfaces and classes, but are always implicitly final, and thus get the behavior above - if you call it through the interface, you get a different func than calling it through the class.




BTW you can also check interface conversion for objects in a template function and get static dispatch that way... sort of:

void something(T : Foo)(T bar) {
        bar.foo();
}
void main() {
        Foo bar = new Bar();  // explicitly using the interface
        something(bar); // leads to this calling "foo"

        // but if you did "auto bar = new Bar();" or "Bar bar"
       // it would call "foo from bar"
}

Reply via email to