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"
}