21 hours ago

On Monday, 3 November 2025 at 08:02:06 UTC, Peter C wrote:

>

On Monday, 3 November 2025 at 07:26:24 UTC, Serg Gini wrote:

>

[...]

Actually I've confused myself (and likely others) because I thought this code below actually compiled at one stage (with no error) - turns out... it won't compile.

[...]

Base doesnt inherit from Isomething, so Base.someMethod doesn't implement the interface.
so Derived sees Isomething and doesnt see any implementation for it. it doesnt simply take the same signature

19 hours ago

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

9 hours ago
On Monday, 3 November 2025 at 10:26:59 UTC, Serg Gini wrote:
> On Monday, 3 November 2025 at 09:32:45 UTC, Peter C wrote:
>> On Monday, 3 November 2025 at 08:34:02 UTC, Serg Gini wrote:
>>> On Monday, 3 November 2025 at 08:02:06 UTC, Peter C wrote:
>> 'the model name' ??
>>
>> Anyway...it's solved now. It turns out, that composition was the answer here.
>
> So just to finalize for anyone who will read it.
> D doesn't have any issues

Well.. I wouldn't go that far ;-)

In C#, you just say "This method is for the interface, and this other one is for my class, even though they share the same signature."

Since D doesn’t support C#-like 'explicit interface declarations' the programmer has to reach for other patterns.

So.. to your question -> programmers can decide for themselves whether they prefer the extra ceremony in D.

As for me, I strongly prefer C#'s neat explicit interface syntax.

9 hours ago
On Monday, 3 November 2025 at 12:29:44 UTC, Quirin Schroll wrote:
>
> ..

Borrowing and idea from Carbon and Rust, you could group all the interface methods together in a dedicated block/scope using 'impl':

It's nice and structured, and would scale very well for handling multiple interfaces.

module myModule;
@safe:
private:

import std.stdio : writeln;

interface IWorker
{
    void start();
    void stop();
    int status();
}

class Base
{
    void start()
    {
        writeln("Base: starting generic process");
    }

    void stop()
    {
        writeln("Base: stopping generic process");
    }

    int status()
    {
        return 0; // 0 = idle
    }
}

class Derived : Base, IWorker
{
    // Explicit interface implementation block
    impl(IWorker)
    {
        void start()
        {
            writeln("IWorker: initializing hardware");
        }

        void stop()
        {
            writeln("IWorker: shutting down hardware");
        }

        int status()
        {
            writeln("IWorker: reporting hardware status");
            return 42; // pretend 42 = "active"
        }
    }
}

void main()
{
    auto d = new Derived();

    // Calls Base methods
    d.start();   // "Base: starting generic process"
    d.stop();    // "Base: stopping generic process"
    writeln(d.status()); // 0

    // Calls IWorker methods
    IWorker w = d;
    w.start();   // "IWorker: initializing hardware"
    w.stop();    // "IWorker: shutting down hardware"
    writeln(w.status()); // 42
}



1 2 3
Next ›   Last »