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:
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 =:
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:
// 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:
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).