digitalmars.D - implement vs override
- Peter C (55/55) Oct 31 NOTE: It's just an idea, not a proposal.
- Peter C (43/43) Oct 31 On Friday, 31 October 2025 at 22:58:04 UTC, Peter C wrote:
- Quirin Schroll (5/13) Oct 31 This is a good idea for nomenclature in documentation, but it
- Peter C (19/36) Oct 31 ok. interesting...
- Peter C (16/54) Oct 31 oops.
- Peter C (40/48) Oct 31 ok. that took me a while to get my head around ;-)
- Dejan Lekic (3/4) Nov 01 There is nothing "accidental" there - you have made the decision
- Peter C (22/27) Nov 01 Just because you know what it means, doesn't mean I know what it
- Dejan Lekic (5/7) Nov 02 I am trying very hard to understand you here - you, as developer
- Peter C (21/28) Nov 02 There is no indication to me that Base intended to implement the
- Serg Gini (3/4) Nov 02 why do you think Base is considered as an implementation of the
- Peter C (31/36) Nov 01 If D had a C# like 'explicit' interface declaration:
- Worldeater (5/38) Nov 02 the whole point of it is to not have to cast to interfaces, but
- Quirin Schroll (61/101) Nov 03 Yes, I ran into this issue in practice in C++. C++/CLI actually
- Peter C (64/65) Nov 03 Borrowing and idea from Carbon and Rust, you could group all the
- Zealot (4/7) Oct 31 yeah, the java exception lists were that too. turns out people
NOTE: It's just an idea, not a proposal.
I'm a big fan of clarity in design.
Clarity is what makes your design understandable and maintainable.
'implement' - implements an abstract/interface method -
First-time definition
'override' - overrrides a concrete base method - Replaces or
extends existing logic
interface Clickable
{
void onClick();
}
class Component
{
void render()
{
writeln("Rendering generic component");
}
}
class Button : Component, Clickable
{
implement void onClick()
{
// First-time implementation of Clickable.onClick
writeln("Button clicked!");
}
override void render()
{
// Overrides Component.render
writeln("Rendering a button");
}
}
---- currently you can do it this way in D, and it provide very
little clarity at all.
interface Clickable
{
void onClick();
}
class Component
{
void render()
{
writeln("Rendering generic component");
}
}
class Button : Component, Clickable
{
void onClick()
{
writeln("Button clicked!");
}
override void render()
{
writeln("Rendering a button");
}
}
Oct 31
On Friday, 31 October 2025 at 22:58:04 UTC, Peter C wrote:to have in D: interface Clickable { void onClick(); } class Component { void render() { writeln("Rendering generic component"); } } class Button : Component, Clickable { void Clickable:onClick() { // First-time implementation of Clickable.onClick writeln("Button clicked!"); } override void render() { // Overrides Component.render writeln("Rendering a button"); } } --- And when it becomes even more confusing: interface Isomething { void someMethod(); } class Base { void someMethod() { } } class Derived : Base, Isomething { override void someMethod() { } // ?? // Error: Method 'someMethod' matches both a base class and interface signature. Use override or explicit interface implementation to clarify." }
Oct 31
On Friday, 31 October 2025 at 22:58:04 UTC, Peter C wrote:NOTE: It's just an idea, not a proposal. I'm a big fan of clarity in design. Clarity is what makes your design understandable and maintainable. 'implement' - implements an abstract/interface method - First-time definition 'override' - overrrides a concrete base method - Replaces or extends existing logicThis 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.
Oct 31
On Friday, 31 October 2025 at 23:36:57 UTC, Quirin Schroll wrote:On Friday, 31 October 2025 at 22:58:04 UTC, Peter C wrote:ok. interesting... interface IGreeter { void greet(); } class Base { void greet() {} // Really, there should be a complier error here. // e.g "Error: Method 'greet' matches both a base class and interface signature." // so ok...what to do here?? remove or rename? // I don't think Base should sucessfully compile under this circumstance. } class Derived : Base, IGreeter { }NOTE: It's just an idea, not a proposal. I'm a big fan of clarity in design. Clarity is what makes your design understandable and maintainable. 'implement' - implements an abstract/interface method - First-time definition 'override' - overrrides a concrete base method - Replaces or extends existing logicThis 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.
Oct 31
On Friday, 31 October 2025 at 23:49:06 UTC, Peter C wrote:On Friday, 31 October 2025 at 23:36:57 UTC, Quirin Schroll wrote:oops. interface IGreeter { void greet(); } class Base { void greet() {} } class Derived : Base, IGreeter { // "Error: class Derived inherits a base class method that matches IGreeter.greet(). Use an explicit interface declaration to implement Greeter.greet()" }On Friday, 31 October 2025 at 22:58:04 UTC, Peter C wrote:ok. interesting... interface IGreeter { void greet(); } class Base { void greet() {} // Really, there should be a complier error here. // e.g "Error: Method 'greet' matches both a base class and interface signature." // so ok...what to do here?? remove or rename? // I don't think Base should sucessfully compile under this circumstance. } class Derived : Base, IGreeter { }NOTE: It's just an idea, not a proposal. I'm a big fan of clarity in design. Clarity is what makes your design understandable and maintainable. 'implement' - implements an abstract/interface method - First-time definition 'override' - overrrides a concrete base method - Replaces or extends existing logicThis 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.
Oct 31
On Friday, 31 October 2025 at 23:36:57 UTC, Quirin Schroll wrote:.. You can implement an interface method by inheriting from a class that defines the method without the base class implementing the interface.ok. that took me a while to get my head around ;-) -------------------------------- interface IsomeInterface { void someMethod(); } class Base { void someMethod() { } // virtual by default in D. } class Derived : Base, IsomeInterface { // Note: no mention of void someMethod() anywhere. } ------------------------------- ok. now we have the 'accidental implementation' problem. The compiler really should produce an error message here, in relation to Derived:Error: 'Base.someMethod' signature conflicts with 'IsomeInterface.someMethod' signature. Add an explicitly declared void someMethod() in Derived, to resolve this ambiquity.Fortunately in D, 'override' is now required to override a base class method. So now, the programmer *must* do either of these things: (1) class Derived : Base, IsomeInterface { // NOTE: D doesn't have an 'implement' keyword for implementing an interface method. void someMethod() {} // implementing the interface contract here } (2) class Derived : Base, IsomeInterface { override void someMethod() {} // overiding the virtual member inherited from Base. } Either way, the compiler is now satisfied that you have resolved the 'accidental implementation' problem. I don't expect D to make a change here, but this is how I would have expected a compiler to behave in any case. I think the Carbon language may have resolved this.
Oct 31
On Saturday, 1 November 2025 at 06:41:57 UTC, Peter C wrote:ok. now we have the 'accidental implementation' problem.There is nothing "accidental" there - you have made the decision to inherit from Base, and should know what that means!
Nov 01
On Saturday, 1 November 2025 at 13:47:22 UTC, Dejan Lekic wrote:On Saturday, 1 November 2025 at 06:41:57 UTC, Peter C wrote:Just because you know what it means, doesn't mean I know what it means. The compiler sure seems to know what it means. But it's not an absolute that in this situation that the programmer would know what it means - and I specifically use myself as a case study here ;-) Also, will the next programmer maintaining your code know what it means? interface Isomething { void someMethod(); } class Base { void someMethod() {} } class Derived : Base, Isomething { // is Derived fullfilling the semantic requirements of interface contract here? }ok. now we have the 'accidental implementation' problem.There is nothing "accidental" there - you have made the decision to inherit from Base, and should know what that means!
Nov 01
On Sunday, 2 November 2025 at 00:00:35 UTC, Peter C wrote:Just because you know what it means, doesn't mean I know what it means.I am trying very hard to understand you here - you, as developer who wrote the code, deliberately made a decision to inherit from Base class. This means you _do know_ what it means (what that class does).
Nov 02
On Sunday, 2 November 2025 at 11:33:56 UTC, Dejan Lekic wrote:On Sunday, 2 November 2025 at 00:00:35 UTC, Peter C wrote:There is no indication to me that Base intended to implement the semantic requirements of the interface. Do you understand that? And yet, Base.someMethod() is considered an implementation of the interface. I understand that the compiler undertands this (because it has the same signature), but really, the compiler is just taking the easiest possible path here. It's still not clear to *me* (regardless of the rules here) that by simply inherting a method from Base that has the same signature, that it automatically satisfies the semantic requirements of the interface. The person maintaining this code will likely ask the same question I did - does Derived implement the semantic requirement of the interface, or not? this question straight away. The intent would have been clear, and I would have understood immediately that Derived has indeed implemented the semantic requirement of the interface. D's starting to remind me of that scene in Ghostbusters, where Peter drives up with (what will become) the ghostbusters vehicle. i.e. look promising, but will need a lot of work.Just because you know what it means, doesn't mean I know what it means.I am trying very hard to understand you here - you, as developer who wrote the code, deliberately made a decision to inherit from Base class. This means you _do know_ what it means (what that class does).
Nov 02
On Sunday, 2 November 2025 at 23:13:08 UTC, Peter C wrote:On Sunday, 2 November 2025 at 11:33:56 UTC, Dejan Lekic wrote:why do you think Base is considered as an implementation of the interface?
Nov 02
On Monday, 3 November 2025 at 07:26:24 UTC, Serg Gini wrote:On Sunday, 2 November 2025 at 23:13:08 UTC, Peter C 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. It will produce an error: Error: class `myModule.Derived` interface function `void someMethod()` is not implemented interface method in a derived class if the signatures match. In D, it seems the rule is a little different: A class that claims to implement an interface must itself provide implementations for all interface methods. Inherited methods from a base class are not counted *unless* the compiler can directly see that the derived class provides them (i.e. via an 'override' of the base method). Turns out I prefer the way D *prevents* this from compiling, and actually requires that you 'override' the method in Derived. That signals an explicit action by the programmer to deal with this The only way to get the code below to compile in D, is to 'override' someMethod in Derived. But... .. what if I need to keep the semantics of the base class method (or override for some reason), but also implement the semantics of the interface contract? - which D does not have. I won't spend more time on this, cause it's pretty rare scenario in the work I do, but I've learnt something useful, so wasn't a complete waste of time - for me anyway ;-) btw. Would be interesting to know if anyone in the past has ever what the response was. ................................. module myModule; import std; void main() { Derived d = new Derived(); d.someMethod(); } interface Isomething { void someMethod(); } class Base { void someMethod() { writeln("Hello from Base"); } } class Derived : Base, Isomething { } .................................On Sunday, 2 November 2025 at 11:33:56 UTC, Dejan Lekic wrote:why do you think Base is considered as an implementation of the interface?
Nov 03
On Monday, 3 November 2025 at 08:02:06 UTC, Peter C wrote:But... .. what if I need to keep the semantics of the base class method (or override for some reason), but also implement the semantics of the interface contract?This is all theoretical - without code example doesn't mean anything. Drop all prompt that was used before and provide the model name that used for this text generation.
Nov 03
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. module myModule; safe: private: import std.stdio : writeln; interface Isomething { void someMethod(); } class Base { void someMethod() { writeln("Hello from Base"); } } class Derived : Isomething { Base base; // composition this() { base = new Base(); } // Interface implementation void someMethod() { writeln("Hello from Isomething in Derived"); } // Expose base behavior separately void callBase() { base.someMethod(); } } void main() { auto d = new Derived(); Isomething i = d; i.someMethod(); // "Hello from Isomething in Derived" d.callBase(); // "Hello from Base" }But... .. what if I need to keep the semantics of the base class method (or override for some reason), but also implement the semantics of the interface contract?This is all theoretical - without code example doesn't mean anything. Drop all prompt that was used before and provide the model name that used for this text generation.
Nov 03
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:So just to finalize for anyone who will read it. D doesn't have any issuesOn 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.
Nov 03
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:Well.. I wouldn't go that far ;-) other one is for my class, even though they share the same signature." 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.On Monday, 3 November 2025 at 08:34:02 UTC, Serg Gini wrote:So just to finalize for anyone who will read it. D doesn't have any issuesOn 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.
Nov 03
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: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[...]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. [...]
Nov 03
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.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. } }
Nov 01
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:the whole point of it is to not have to cast to interfaces, but just have the type behave a certain way. just use plain old composition if and alias the methods if you want this.[...]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. } }
Nov 02
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: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 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).... 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.```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. } } ```
Nov 03
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 }
Nov 03
On Friday, 31 October 2025 at 22:58:04 UTC, Peter C wrote:'implement' - implements an abstract/interface method - First-time definitionuse implement and build your own checker if you need this.I'm a big fan of clarity in design.yeah, the java exception lists were that too. turns out people hate useless clutter and extra work.
Oct 31
On Friday, 31 October 2025 at 23:39:29 UTC, Zealot wrote:On Friday, 31 October 2025 at 22:58:04 UTC, Peter C wrote:Java's `throws` is kinda cute I think.'implement' - implements an abstract/interface method - First-time definitionuse implement and build your own checker if you need this.I'm a big fan of clarity in design.yeah, the java exception lists were that too. turns out people hate useless clutter and extra work.
Oct 31
On Friday, 31 October 2025 at 23:39:29 UTC, Zealot wrote:On Friday, 31 October 2025 at 22:58:04 UTC, Peter C wrote:I kinda meant 'clarity to avoid ambiguity', not clarity to create clutter and extra work.'implement' - implements an abstract/interface method - First-time definitionuse implement and build your own checker if you need this.I'm a big fan of clarity in design.yeah, the java exception lists were that too. turns out people hate useless clutter and extra work.
Oct 31









Peter C <peterc gmail.com> 