implement vs override

Quirin Schroll qs.il.paperinik at gmail.com
Mon Nov 3 12:29:44 UTC 2025


On Sunday, 2 November 2025 at 00:49:36 UTC, Peter C wrote:
> On Friday, 31 October 2025 at 23:36:57 UTC, Quirin Schroll 
> wrote:
>>
>> ...
>> This is a good idea for nomenclature in documentation, but it 
>> doesn't work with the language. You can implement an interface 
>> method by inheriting from a class that defines the method 
>> without the base class implementing the interface.
>
> If D had a C# like 'explicit' interface declaration:
> ```d
> module myModule;
> @safe:
> private:
>
> void main()
> {
>
> }
>
> interface Isomething
> {
>     void someMethod();
> }
>
> class Base
> {
>
>     void someMethod()
>     {
>
>     }
> }
>
> class Derived : Base, Isomething
> {
>   // Here, I am intentionally binding the interface requirement
>   // to a concrete method, rather than letting the inherited 
> method automatically
>   // fulfill the interface contract.
>
>   void ISomething.SomeMethod()
>   {
>     // This method satisfies the interface, but it's only 
> accessible
>     // when the object is cast to the ISomething type.
>   }
> }
> ```

Yes, I ran into this issue in practice in C++. C++/CLI actually 
supports this quite elegantly (elegantly for C++) using `=`:
```cpp
class Derived : public Base, public Interface
{
     …
     void myCustomName() const = Interface::interfaceMethod;
};
void Derived::myCustomName() const { … }
```

This is an actual limitation in D (and IIRC, also in Java): If 
two interfaces have methods with the same name and parameter 
list, you ***cannot*** implement them differently. This defeats 
the whole purpose of interfaces which are supposed not to be duck 
typing (it’s a duck if and only if it happens to have `void 
quack()`), but explicit (it’s a duck if and only if it implements 
`std.quacking.IDuck`).

I think I suggested something like that for D, hooking the 
`override` keyword:
```d
// My proposal from memory
interface I1 { void iface(int); }
interface I2 { void iface(int); }

class C : I1, I2
{
     override(I1)
     void iface1(int) { }

     override(I2)
     void iface2(int) { }
}

void main()
{
     C c = new C;
     c.iface(); // Error, `C` does not have `iface`; did you mean 
`iface1` or `iface2`?
     c.I1.iface(); // Okay
     c.I2.iface(); // Okay
}
```

The original proposal went further and would also allow overrides 
contravariant in parameter lists:
```d
class Base { }
class Derived : Base { }

interface I { Base f(Derived); }

class C : I
{
     override(I.f(Derived))
     Derived f(Base) const => new Derived;
}
```
 From a theoretical and implementation (vtable) standpoint, 
there’s nothing wrong with doing this. It’s completely in-line 
with the Liskov substitution principle.

On the topic of the original post, the difference between a base 
class and an interface is very minor. D, Java, C#, and many other 
single-inheritance languages make you have a trade-off between an 
inheritable construct having non-static data members (class) and 
allowing it to be freely inherited from alongside something else 
(interface).


More information about the Digitalmars-d mailing list