Bug 16318 – inherit from interface via abstract class
Status
RESOLVED
Resolution
DUPLICATE
Severity
enhancement
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2016-07-24T19:09:51Z
Last change time
2020-03-21T03:56:40Z
Keywords
spec
Assigned to
No Owner
Creator
Lodovico Giaretta
Comments
Comment #0 by lodovico — 2016-07-24T19:09:51Z
interface Foo
{
void foo();
}
abstract class Bar: Foo
{
// the following line eliminates the error, if uncommented
// abstract override void foo();
}
class Baz: Bar
{
override void foo();
// error: Baz.foo does not override any function;
// did you meant to override Foo.foo?
}
Why doesn't this work? Probably there's a good reason, but I can't find it.
I would think that the commented-out line was implicit, but it is not.
Comment #1 by b2.temp — 2016-08-12T00:29:17Z
Your request is not valid because it already works. You forget that an interface method has to be implemented at least once before being overridden, otherwise what do you override ? An interface method is not like an abstract method and the error message couldn't be more accurate.
°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
interface Foo
{
void foo();
}
abstract class Bar: Foo {}
class Baz: Bar
{
void foo(uint i){}
void foo(){}
}
void main()
{
(cast(Foo) new Baz).foo;
}
°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
I let you close.
Comment #2 by lodovico — 2016-08-12T07:54:20Z
(In reply to b2.temp from comment #1)
> Your request is not valid because it already works. You forget that an
> interface method has to be implemented at least once before being
> overridden, otherwise what do you override ? An interface method is not like
> an abstract method and the error message couldn't be more accurate.
Sorry, I don't understand your reasoning, so I'd love if you could answer the following points. Thank you in advance for spending your time on this.
If I inherit directly from an interface, I can override:
==================
interface IFoo { void foo(); }
class FooImpl: IFoo { override void foo(); } // override here is fine
==================
It seems counterintuitive that you can't do this transitively:
==================
interface IFoo { void foo(); }
abstract class AFoo: IFoo {}
class FooImpl: AFoo { override void foo(); } // override here does not work
==================
It is true that it works if I remove "override", but this makes it unclear that FooImpl.foo overrides IFoo.foo. When I encountered this, it made me think that FooImpl.foo was just hiding IFoo.foo because of some signature error I did.
Also, I have an interface with *lots* of methods, and an abstract base class that only implements a tiny portion of them. Having to explicitly enumerate the methods that I'm not implementing bloats my code.
Comment #3 by b2.temp — 2016-08-12T14:13:07Z
(In reply to Lodovico Giaretta from comment #2)
> (In reply to b2.temp from comment #1)
> > Your request is not valid because it already works. You forget that an
> > interface method has to be implemented at least once before being
> > overridden, otherwise what do you override ? An interface method is not like
> > an abstract method and the error message couldn't be more accurate.
>
> Sorry, I don't understand your reasoning, so I'd love if you could answer
> the following points. Thank you in advance for spending your time on this.
>
> If I inherit directly from an interface, I can override:
>
> ==================
> interface IFoo { void foo(); }
>
> class FooImpl: IFoo { override void foo(); } // override here is fine
I suspect this usage of "override" of being an noop.
We need an exact analysis from a DMD expert here.
> ==================
>
> It seems counterintuitive that you can't do this transitively:
>
> ==================
> interface IFoo { void foo(); }
>
> abstract class AFoo: IFoo {}
>
> class FooImpl: AFoo { override void foo(); } // override here does not work
> ==================
>
> It is true that it works if I remove "override", but this makes it unclear
> that FooImpl.foo overrides IFoo.foo.
FooImpl.foo doesn't **override** IFoo.foo, it **implements** IFOO.foo.
The compiler will throw an error if you forget. Here you argument is really a matter of taste. I can say that what makes unclear that IFOO is implemented because an abstract class is used in the middle.
> When I encountered this, it made me
> think that FooImpl.foo was just hiding IFoo.foo because of some signature
> error I did.
Anyway, it's a DUP
*** This issue has been marked as a duplicate of issue 2525 ***
Comment #4 by lodovico — 2016-08-12T14:28:20Z
(In reply to b2.temp from comment #3)
> (In reply to Lodovico Giaretta from comment #2)
> > If I inherit directly from an interface, I can override:
> >
> > ==================
> > interface IFoo { void foo(); }
> >
> > class FooImpl: IFoo { override void foo(); } // override here is fine
>
> I suspect this usage of "override" of being an noop.
> We need an exact analysis from a DMD expert here.
If what you say is correct, that is very bad. It gives a wrong idea of what override does really mean. See my next comment.
> > It seems counterintuitive that you can't do this transitively:
> >
> > ==================
> > interface IFoo { void foo(); }
> >
> > abstract class AFoo: IFoo {}
> >
> > class FooImpl: AFoo { override void foo(); } // override here does not work
> > ==================
> >
> > It is true that it works if I remove "override", but this makes it unclear
> > that FooImpl.foo overrides IFoo.foo.
>
> FooImpl.foo doesn't **override** IFoo.foo, it **implements** IFOO.foo.
>
> The compiler will throw an error if you forget. Here you argument is really
> a matter of taste. I can say that what makes unclear that IFOO is
> implemented because an abstract class is used in the middle.
Ok, I gave override a different meaning. I can accept this, but then IMO we need a way to say "this methods implements an interface method". It is at least as useful as "this method overrides another method", so much that I (and probably many other programmers) conflate the two meanings into one "this method is part of another API, not a specific feature of the current class".
Comment #5 by schveiguy — 2016-08-12T15:13:02Z
Requiring override for implementing interface methods is too strict. If a class defines an interface, and doesn't implement a method, compilation fails. So we don't need that warning/error.
Allowing override for interfaces is fine too. Often times, one decides that an abstract class really should be an interface or vice versa. To have to go through and update all the methods to say or not say override is useless busywork.
Bottom line is that pure virtual functions should allow override, and not require it, no matter what the source. In effect, since implementing is REQUIRED, override keyword is a noop.
Comment #6 by aliloko — 2017-11-12T21:59:57Z
I lost a lot of time on that issue
---------------------
interface A
{
void lol();
}
abstract class B : A
{
}
class C : B
{
override void lol()
{
}
}
----------------------
Error: function f891.C.lol does not override any function, did you mean to override 'f891.A.lol'?
----------------------
It's very unclear and unpexpected that the proper fix is just to remove the "override" keyword.