www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - method returning child, doesn't overrides declared method returning parent

reply Mariusz =?UTF-8?B?R2xpd2nFhHNraQ==?= <alienballance gmail.com> writes:
<code>
interface Interface {
	Interface method();
}
class Class : Interface {
	override Class method() {}
}
</code>

DMD complains it isn't overriding. How should it be according to 
specification, and how about making it legal?
Aug 29 2011
next sibling parent reply "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Monday, August 29, 2011 14:09 Mariusz Gliwiński wrote:
 <code>
 interface Interface {
 Interface method();
 }
 class Class : Interface {
 override Class method() {}
 }
 </code>
 
 DMD complains it isn't overriding. How should it be according to
 specification, and how about making it legal?

It's _not_ overriding. It's implementing an interface method. Those are two totally different things. And I think that it's horrible that Java considers implementing an interface method as overriding it. I'd _hate_ to see that in D. - Jonathan M Davis
Aug 29 2011
next sibling parent reply Mariusz =?UTF-8?B?R2xpd2nFhHNraQ==?= <alienballance gmail.com> writes:
Jonathan M Davis wrote:
 It's _not_ overriding. It's implementing [...]

Whether it's called overriding or implementing isn't a big deal for me. In D we *already* write _override_ keyword to _implement_ method (IMO it's good choice, to match with overriding class methods). But back to the topic, it would be like that: * we have object which implements interface * we have method that returns objects implementing this interface * we want to return object which implements this interface * we can't return it as class (implementation of interface + something more), because we have to be seen ONLY as implementation of this interface result: We have to declare method, that returns child object, then make a proxy to narrow and override interface. So it looks like: <code> Class real_method() {} override Interface method() {stupid_method();} </code> Ps. If someone felt offended by calling "object, that implements interface" a "child object", i'm sorry for that. Thanks, Mariusz Gliwiński
Aug 29 2011
parent reply Mariusz =?UTF-8?B?R2xpd2nFhHNraQ==?= <alienballance gmail.com> writes:
Jonathan M Davis wrote:
 This seems to compile just fine:
 
 interface Interface
 {
  Interface method();
 }
 class Class : Interface
 {
  Class method() {return new Class;}
 }
 
 The problem is the override keyword. _No_ overriding is going on. _That's_
 why it's complaining.

I'm sorry - i provided wrong example. I had property in my code, and he didn't complained about getter, but setter (of course he can't diversify by different return values). <code> interface Interface { void method(Interface); } class Class : Interface { void method(Class) {} } void main() {} </code> So, You're saying it should be possible, and this is DMD bug? So i'll report that. Thanks, Mariusz G.
Aug 29 2011
parent Mariusz =?UTF-8?B?R2xpd2nFhHNraQ==?= <alienballance gmail.com> writes:
Jonathan M Davis wrote:
 On Tuesday, August 30, 2011 08:57:53 Mariusz Gliwiński wrote:
[...]
 <code>
 interface Interface
 {
 void method(Interface);
 }
 class Class : Interface
 {
 void method(Class) {}
 }
 
 void main() {}
 </code>

This particular example is not a bug. [...]

You're absolutely right, it's not symetric. Now i have to think a bit because i highly relied on this. I'm sorry for taking Your time. Thanks, Mariusz Gliwiński
Aug 30 2011
prev sibling next sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 08/29/2011 10:24 PM, Jonathan M Davis wrote:
 On Monday, August 29, 2011 14:09 Mariusz Gliwiński wrote:
 <code>
 interface Interface {
 Interface method();
 }
 class Class : Interface {
 override Class method() {}
 }
 </code>

 DMD complains it isn't overriding. How should it be according to
 specification, and how about making it legal?

It's _not_ overriding. It's implementing an interface method. Those are two totally different things. And I think that it's horrible that Java considers implementing an interface method as overriding it. I'd _hate_ to see that in D.

+1 override should be required when there already is an implementation and disallowed when there is not.
Aug 30 2011
prev sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 08/30/2011 01:48 PM, Marco Leise wrote:
 Am 29.08.2011, 22:24 Uhr, schrieb Jonathan M Davis <jmdavisProg gmx.com>:

 It's _not_ overriding. It's implementing an interface method. Those
 are two
 totally different things. And I think that it's horrible that Java
 considers
 implementing an interface method as overriding it. I'd _hate_ to see
 that in
 D.

 - Jonathan M Davis

This design decision in Java isn't particularly bad I think. Look at how dim the line is between an interface, an abstract class and a class. Some languages use the notion of a fully abstract class for interfaces. In case you implement one interface and it is somewhat internal you may choose to provide some default implementations and turn it into an abstract class.

At that point, probably everything breaks, because you cannot inherit from multiple classes.
 At this point you should add 'override' to the all
 descendant classes that override these implementations.If override was
 mandatory you could easily spot any methods that correspond to something
 higher in the hierarchy (extended class / interface). What would you
 argue for when you implement a method of an abstract class for example?
 Does it override or implement?

If there already is an implementation, it overrides it, otherwise it implements it. Easily spotting methods that correspond to something higher in the hierarchy is achieved best with comments. (You actually see to which parent of the class a method belongs.) class C: I{ void somemethod() { } /* interface I */ void someinterfacemethod() { } void someotherinterfacemethod() { } /* class Object */ override string toString() { } }
 But D is not Java and there are already cases of implicit interfaces
 (Range). So it makes sense not to be overly verbose with interfaces in D.

I agree.
Aug 30 2011
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 08/30/2011 07:13 AM, Timon Gehr wrote:
 If there already is an implementation, it overrides it, otherwise it
 implements it.

That's pretty much it. The entire purpose of the "override" keyword is to prevent silent bugs of two kinds: (a) User thinks she hooks a specific method but instead introduces a new one. (b) User thinks she introduces a new method but instead hooks one. Override helps only in cases where otherwise a silent error would occur. If the compiler issues an error message without the help of override, override is unneeded and illegal. This is the case with interface and abstract methods - "override" is emphatically unneeded because the compiler/linker wouldn't allow the code anyway. Andrei
Aug 30 2011
next sibling parent travert phare.normalesup.org (Christophe) writes:
I'm not sure what I am talking about (I have never used interfaces so 
far), but if a interface developper adds a method foo, she expects every 
developper of derived class to get an error because they don't implement 
this new method yet.

But if a derived class unfortunately already has a method called foo. 
The developped of the derived class will not be aware that the interface 
has changed, and his method foo is propably not what is expected by the 
interface developper. The compiler will not complain about the absence 
of the override (or implement?) keyword. This may be a serious problem. 
The only solution is to never add new interface methods without 
providing default solutions for these methods.

-- 
Christophe
Aug 30 2011
prev sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 8/30/11 7:45 AM, Steven Schveighoffer wrote:
 On Tue, 30 Aug 2011 08:26:17 -0400, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:

 On 08/30/2011 07:13 AM, Timon Gehr wrote:
 If there already is an implementation, it overrides it, otherwise it
 implements it.

That's pretty much it. The entire purpose of the "override" keyword is to prevent silent bugs of two kinds: (a) User thinks she hooks a specific method but instead introduces a new one. (b) User thinks she introduces a new method but instead hooks one. Override helps only in cases where otherwise a silent error would occur. If the compiler issues an error message without the help of override, override is unneeded and illegal. This is the case with interface and abstract methods - "override" is emphatically unneeded because the compiler/linker wouldn't allow the code anyway.

Your (a) and (b) points seem to be pointing to a different conclusion -- that override should be required for interface methods.

No, because the compiler rejects code that doesn't implement all methods of an interface. Andrei
Aug 30 2011
next sibling parent reply travert phare.normalesup.org (Christophe) writes:
The fact that the code compile only if all interface methods are 
implemented does not imply that the programmer knows which method he 
implemented hooks and which does not.
Aug 30 2011
next sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 08/30/2011 05:49 PM, Christophe wrote:
 The fact that the code compile only if all interface methods are
 implemented does not imply that the programmer knows which method he
 implemented hooks and which does not.

interface I{ void method(); } class C: I{ void method() {} // not a hook. }
Aug 30 2011
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 08/30/2011 06:00 PM, Steven Schveighoffer wrote:
 On Tue, 30 Aug 2011 11:58:43 -0400, Timon Gehr <timon.gehr gmx.ch> wrote:

 On 08/30/2011 05:49 PM, Christophe wrote:
 The fact that the code compile only if all interface methods are
 implemented does not imply that the programmer knows which method he
 implemented hooks and which does not.

interface I{ void method(); } class C: I{ void method() {} // not a hook. }

Why not? All a "hook" is is adding an entry into a base class' vtable. This is no different, it's just the base "class" is an interface. -Steve

As far as I can tell, a hook is overwriting an existing entry.
Aug 30 2011
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 08/30/2011 06:23 PM, Steven Schveighoffer wrote:
 On Tue, 30 Aug 2011 12:18:32 -0400, Timon Gehr <timon.gehr gmx.ch> wrote:

 On 08/30/2011 06:00 PM, Steven Schveighoffer wrote:
 On Tue, 30 Aug 2011 11:58:43 -0400, Timon Gehr <timon.gehr gmx.ch>
 wrote:

 On 08/30/2011 05:49 PM, Christophe wrote:
 The fact that the code compile only if all interface methods are
 implemented does not imply that the programmer knows which method he
 implemented hooks and which does not.

interface I{ void method(); } class C: I{ void method() {} // not a hook. }

Why not? All a "hook" is is adding an entry into a base class' vtable. This is no different, it's just the base "class" is an interface. -Steve

As far as I can tell, a hook is overwriting an existing entry.

Nothing is "overwritten", what's written into the table is decided at compile-time. -Steve

It is conceptually "overwritten" at compile time: Copy vtable from parent and replace the overriden entries. And I am quite certain that what exactly is in the table is actually decided at link time.
Aug 30 2011
next sibling parent "Daniel Murphy" <yebblies nospamgmail.com> writes:
"Timon Gehr" <timon.gehr gmx.ch> wrote in message 
news:j3j4m4$2l0u$1 digitalmars.com...
 And I am quite certain that what exactly is in the table is actually 
 decided at link time.

At object file generation time generally.
Aug 30 2011
prev sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 08/30/2011 07:06 PM, Steven Schveighoffer wrote:
 On Tue, 30 Aug 2011 12:55:30 -0400, Timon Gehr <timon.gehr gmx.ch> wrote:

 On 08/30/2011 06:23 PM, Steven Schveighoffer wrote:
 On Tue, 30 Aug 2011 12:18:32 -0400, Timon Gehr <timon.gehr gmx.ch>
 wrote:

 On 08/30/2011 06:00 PM, Steven Schveighoffer wrote:
 On Tue, 30 Aug 2011 11:58:43 -0400, Timon Gehr <timon.gehr gmx.ch>
 wrote:

 On 08/30/2011 05:49 PM, Christophe wrote:
 The fact that the code compile only if all interface methods are
 implemented does not imply that the programmer knows which method he
 implemented hooks and which does not.

interface I{ void method(); } class C: I{ void method() {} // not a hook. }

Why not? All a "hook" is is adding an entry into a base class' vtable. This is no different, it's just the base "class" is an interface. -Steve

As far as I can tell, a hook is overwriting an existing entry.

Nothing is "overwritten", what's written into the table is decided at compile-time. -Steve

It is conceptually "overwritten" at compile time: Copy vtable from parent and replace the overriden entries.

And that's no different from implementing an interface, or an abstract class that does not implement an interface completely -- copy the vtable and overwrite the entries.

interfaces don't possess an own vtable. It is created from scratch for each class implementing the interface.
Aug 30 2011
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 08/30/2011 07:29 PM, Steven Schveighoffer wrote:
 On Tue, 30 Aug 2011 13:21:09 -0400, Timon Gehr <timon.gehr gmx.ch> wrote:

 On 08/30/2011 07:06 PM, Steven Schveighoffer wrote:
 On Tue, 30 Aug 2011 12:55:30 -0400, Timon Gehr <timon.gehr gmx.ch>
 wrote:

 On 08/30/2011 06:23 PM, Steven Schveighoffer wrote:
 On Tue, 30 Aug 2011 12:18:32 -0400, Timon Gehr <timon.gehr gmx.ch>
 wrote:

 On 08/30/2011 06:00 PM, Steven Schveighoffer wrote:
 On Tue, 30 Aug 2011 11:58:43 -0400, Timon Gehr <timon.gehr gmx.ch>
 wrote:

 On 08/30/2011 05:49 PM, Christophe wrote:
 The fact that the code compile only if all interface methods are
 implemented does not imply that the programmer knows which
 method he
 implemented hooks and which does not.

interface I{ void method(); } class C: I{ void method() {} // not a hook. }

Why not? All a "hook" is is adding an entry into a base class' vtable. This is no different, it's just the base "class" is an interface. -Steve

As far as I can tell, a hook is overwriting an existing entry.

Nothing is "overwritten", what's written into the table is decided at compile-time. -Steve

It is conceptually "overwritten" at compile time: Copy vtable from parent and replace the overriden entries.

And that's no different from implementing an interface, or an abstract class that does not implement an interface completely -- copy the vtable and overwrite the entries.

interfaces don't possess an own vtable. It is created from scratch for each class implementing the interface.

The vtable for the interface is identical in layout for each class implementing it.

What I was saying is not that there is no specific layout, just that an interface by itself does not need to be represented in the object file. All interface vtbls are part of the classinfo of the implementing classes. in interface I{ void method(); } class C: I{ void method(){} } No overriding of an existing implementation is taking place, the interface inheritance creates a new interface vtable.
 So if foo() lives at index 0 in the function table for
 class C, it lives at index 0 for class D as well. Otherwise,
 polymorphism wouldn't work, and neither would delegates to interfaces.

 When you call an interface function, the thunk subtracting the offset to
 get to the class pointer is done by a pre-function code piece, then the
 real function is jumped to.

 So yes, each interface has its own vtable layout, similar to how an
 abstract class with no implementations would have its own vtable, even
 though it's not instantiable.

Why would an abstract class without implementations need a vtable in the object file?
Aug 30 2011
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 08/30/2011 08:32 PM, Steven Schveighoffer wrote:
 On Tue, 30 Aug 2011 14:27:25 -0400, Timon Gehr <timon.gehr gmx.ch> wrote:

 What I was saying is not that there is no specific layout, just that
 an interface by itself does not need to be represented in the object
 file. All interface vtbls are part of the classinfo of the
 implementing classes.

 in

 interface I{
 void method();
 }
 class C: I{
 void method(){}
 }

 No overriding of an existing implementation is taking place, the
 interface inheritance creates a new interface vtable.

OK I really can't continue this :) The details we are discussing are abstractly defined in the compiler, and really should have no place in whether something is a 'hook' or not. It really just depends on how you look at it.

I guess so. :)
Aug 30 2011
prev sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 8/30/11 10:49 AM, Christophe wrote:
 The fact that the code compile only if all interface methods are
 implemented does not imply that the programmer knows which method he
 implemented hooks and which does not.

It does mean the programmer implemented all methods of the interface. Andrei
Aug 30 2011
prev sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 8/30/11 11:06 AM, Steven Schveighoffer wrote:
 When I write code that derives from a base class, I'm declaring with
 override that I want to implement the base class' function.
 When I write code that implements an interface, I'm declaring with
 override that I want to implement the interface's function.

From the cycle "deadpan answers": I think one should use "override" when one wants to override. Andrei
Aug 30 2011
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 08/30/2011 06:43 PM, Steven Schveighoffer wrote:
 On Tue, 30 Aug 2011 12:29:59 -0400, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:

 On 8/30/11 11:06 AM, Steven Schveighoffer wrote:
 When I write code that derives from a base class, I'm declaring with
 override that I want to implement the base class' function.
 When I write code that implements an interface, I'm declaring with
 override that I want to implement the interface's function.

From the cycle "deadpan answers": I think one should use "override" when one wants to override.

Then your description of cases where override helps prevent bugs should reflect that: (a) User thinks she overrides a specific method but instead introduces a new one. (b) User thinks she introduces a new method but instead overrides one. I consider implementing an interface method to be hooking, since you are hooking calls from said interface. I guess if we want to avoid solving all hooking problems, even those where one does not intend to implement an interface, but accidentally does, or introduce large annoyances where someone changes a widely used interface to an abstract class, then I guess the status quo is good. -Steve

I don't think that you can change a widely used interface into an abstract class and not introduce annoyances much larger than override is capable of creating. How does the status quo prevent implementing interface methods by accident?
Aug 30 2011
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 08/30/2011 07:16 PM, Steven Schveighoffer wrote:
 On Tue, 30 Aug 2011 13:06:02 -0400, Timon Gehr <timon.gehr gmx.ch> wrote:

 On 08/30/2011 06:43 PM, Steven Schveighoffer wrote:
 On Tue, 30 Aug 2011 12:29:59 -0400, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:

 On 8/30/11 11:06 AM, Steven Schveighoffer wrote:
 When I write code that derives from a base class, I'm declaring with
 override that I want to implement the base class' function.
 When I write code that implements an interface, I'm declaring with
 override that I want to implement the interface's function.

From the cycle "deadpan answers": I think one should use "override" when one wants to override.

Then your description of cases where override helps prevent bugs should reflect that: (a) User thinks she overrides a specific method but instead introduces a new one. (b) User thinks she introduces a new method but instead overrides one. I consider implementing an interface method to be hooking, since you are hooking calls from said interface. I guess if we want to avoid solving all hooking problems, even those where one does not intend to implement an interface, but accidentally does, or introduce large annoyances where someone changes a widely used interface to an abstract class, then I guess the status quo is good. -Steve

I don't think that you can change a widely used interface into an abstract class and not introduce annoyances much larger than override is capable of creating.

interface I { int foo(); void bar(); } -> interface _I { int foo(); void bar(); } abstract class I : _I { int foo() { return 0; } } Now, everywhere I was implemented before has to change all their implementations of foo() to override, just to compile. There may be some cases where classes already had a base class, but it depends on the context of where I is implemented.

That is what I meant.
 However, in 100% of
 the cases, putting override on each implementation of foo does *not*
 result in a bug.

I agree.
 My point is, what "bug" is it preventing by rejecting override when
 implementing an interface? The only "bug" I see is that you didn't put
 override in the signature. That translates to an annoyance, not a real bug.

This one: interface I{ void method1(); void method2(); void method3(); } class C: I{ override void method1(){ ... } override void method2(){ ... } override void method3(){ ... } } => // refactoring implementations of I in C to abstract class D interface I{ void method1(); void method2(); void method3(); } abstract class D: I{ override void method1(){ ... } override void method2(){ ... } override void method3(){ ... } } class C: D{ // left method2() inside class C by accident override void method2(){ ... } // override makes compiler shut up }
 How does the status quo prevent implementing interface methods by
 accident?

It doesn't. That was my point.

Aug 30 2011
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 08/30/2011 07:50 PM, Steven Schveighoffer wrote:
 We could find cases like this all day.

 Make I a class, and this problem also occurs.

 Without the compiler having access to the *changes* it cannot be perfect
 in detecting refactoring errors.

 -Steve

Chances are that it will detect more errors if "override" actually means override.
Aug 30 2011
next sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 08/30/2011 08:35 PM, Steven Schveighoffer wrote:
 On Tue, 30 Aug 2011 14:30:42 -0400, Timon Gehr <timon.gehr gmx.ch> wrote:

 On 08/30/2011 07:50 PM, Steven Schveighoffer wrote:
 We could find cases like this all day.

 Make I a class, and this problem also occurs.

 Without the compiler having access to the *changes* it cannot be perfect
 in detecting refactoring errors.

 -Steve

Chances are that it will detect more errors if "override" actually means override.

Is it just the name? What if it was implement? or override_or_implement? Would that make it "detect more errors"?

I am saying: override_or_implement naturally will detect less errors because it is less specific. Based on context it either means "do nothing special" or "override that method". (that is the current behavior of "override" of course) Renaming the keyword would make its current meaning more explicit, it wouldn't make it detect more errors.
 I can't see how finding more bugs is a bad thing, regardless of what the
 name of the keyword is.

Aug 30 2011
parent travert phare.normalesup.org (Christophe) writes:
Personnally, I would like override to be used when implementing 
interfaces too, because there is really some hooking happening (and 
thus hijacking risks), regardless of the presence of a previous method 
or not.

If the problem is that you may have a method witch overrides an abstract 
class C when the overide keyword was meant for an interface before 
restructuring, well, that can happen. Let's take your example:

interface I { void foo(); }
class C:I { override void foo(); }

-> becomes ->

interface I { void foo(); }
class B:I { override void foo(); }
class C:B { override void foo(); } // left by mistake

Maybe foo was left by mistake, but from the beginning (before creating 
class B), the method was meant to override I, so it must not be that 
bad. Moreover, the override keyword is present, so you should be careful 
when looking at class C. This seems to me to be less important that 
implementing an interface by mistake (apparently not to everybody). 
Anyway this could happen anyway if 'I' was an abstract class at the 
beginning.

If you are concerned by knowing exactly what you override (ant it's a 
good thing) when you use the override keyword, the langage should help 
you with an argument to the override attribute:

interface I { void foo(); }
class B:I { override(I) void foo(); }
class C:B { override(I) void foo(); } // left by mistake
            ^ error: foo() is overriding B.foo()

abstract class B2:I { }
class C2:B2 { override(I) void foo(); } // would works fine
class C3:B2 { override(B) void foo(); }
              ^ error: foo() is overriding I.foo()

The argument to override should be optionnal, so that every good code 
will not be broken.

Cheers.
-- 
Christophe Travert
Aug 30 2011
prev sibling next sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Tuesday, August 30, 2011 11:35 Steven Schveighoffer wrote:
 On Tue, 30 Aug 2011 14:30:42 -0400, Timon Gehr <timon.gehr gmx.ch> wrote:
 On 08/30/2011 07:50 PM, Steven Schveighoffer wrote:
 We could find cases like this all day.
 
 Make I a class, and this problem also occurs.
 
 Without the compiler having access to the *changes* it cannot be perfect
 in detecting refactoring errors.
 
 -Steve

Chances are that it will detect more errors if "override" actually means override.

Is it just the name? What if it was implement? or override_or_implement? Would that make it "detect more errors"? I can't see how finding more bugs is a bad thing, regardless of what the name of the keyword is.

I think that if you wanted full control such that a function is always overriding when you want it and never when you don't want it to and such that it's always implementing when you want it to and never when you don't want it to, then we're going to need to add implements (or more likely, implements) on top of override. The two concepts are similar but separate, and overloading override to do both just creates a separate set of problems (e.g. you thought that a function was overriding a base class function and implementing an interface and now it's just implementing an interface, so you don't catch the fact that the base class function is gone unless you were explictly calling it in the derived function). So, if we were to make a change, I'd argue for adding implements rather than altering how override works. - Jonathan M Davis
Aug 30 2011
prev sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 30 Aug 2011 17:41:46 -0400, Jonathan M Davis <jmdavisProg gmx.com>  
wrote:

 On Tuesday, August 30, 2011 11:35 Steven Schveighoffer wrote:
 On Tue, 30 Aug 2011 14:30:42 -0400, Timon Gehr <timon.gehr gmx.ch>  
 wrote:
 On 08/30/2011 07:50 PM, Steven Schveighoffer wrote:
 We could find cases like this all day.

 Make I a class, and this problem also occurs.

 Without the compiler having access to the *changes* it cannot be  


 in detecting refactoring errors.

 -Steve

Chances are that it will detect more errors if "override" actually

 override.

Is it just the name? What if it was implement? or override_or_implement? Would that make it "detect more errors"? I can't see how finding more bugs is a bad thing, regardless of what the name of the keyword is.

I think that if you wanted full control such that a function is always overriding when you want it and never when you don't want it to and such that it's always implementing when you want it to and never when you don't want it to, then we're going to need to add implements (or more likely, implements) on top of override. The two concepts are similar but separate, and overloading override to do both just creates a separate set of problems (e.g. you thought that a function was overriding a base class function and implementing an interface and now it's just implementing an interface, so you don't catch the fact that the base class function is gone unless you were explictly calling it in the derived function). So, if we were to make a change, I'd argue for adding implements rather than altering how override works.

Again, if the intention of your override keyword is to override all base class/interface functionality, who cares what changes underneath? As long as the hook is still present, there is no error when the base class disappears. I see zero value for separating implements from override. The main purpose of override is to say "I expect that some base class (or interface) declares this function, and I want to write an implementation for it". I agree that override for interfaces is not necessary in some cases (for example, if you write the incorrect signature, it's an error anyway), but there are some cases where it helps. I don't see what the *harm* is in using it, it's already there. -Steve
Aug 31 2011
prev sibling next sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Monday, August 29, 2011 15:18 Mariusz Gliwiński wrote:
 Jonathan M Davis wrote:
 It's _not_ overriding. It's implementing [...]

Whether it's called overriding or implementing isn't a big deal for me. In D we *already* write _override_ keyword to _implement_ method (IMO it's good choice, to match with overriding class methods). But back to the topic, it would be like that: * we have object which implements interface * we have method that returns objects implementing this interface * we want to return object which implements this interface * we can't return it as class (implementation of interface + something more), because we have to be seen ONLY as implementation of this interface result: We have to declare method, that returns child object, then make a proxy to narrow and override interface. So it looks like: <code> Class real_method() {} override Interface method() {stupid_method();} </code> Ps. If someone felt offended by calling "object, that implements interface" a "child object", i'm sorry for that.

This seems to compile just fine: interface Interface { Interface method(); } class Class : Interface { Class method() {return new Class;} } The problem is the override keyword. _No_ overriding is going on. _That's_ why it's complaining. - Jonathan M Davis
Aug 29 2011
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Tuesday, August 30, 2011 08:57:53 Mariusz Gliwi=C5=84ski wrote:
 I'm sorry - i provided wrong example. I had property in my code, and =

 didn't complained about getter, but setter (of course he can't divers=

 different return values).
=20
 <code>
 interface Interface
 {
 =09void method(Interface);
 }
 class Class : Interface
 {
 =09void method(Class) {}
 }
=20
 void main() {}
 </code>
=20
 So, You're saying it should be possible, and this is DMD bug? So i'll=

 that.

This particular example is not a bug. A function which returns a Class = can be=20 used in exactly the same situations as one which returns an Interface, = because=20 an instance of Class _is_ an instance of Interface. However, an instanc= e of=20 Interface is not necessarily an instance of Class. So, if method takes = an=20 instance of Class, it can't take an instance of Interface unless it's a= lso a=20 Class. So, if you had Interface i =3D funcWhichReturnsInterface(); Class c =3D new Class; i.method(c); //This will compile. c.method(i); //This won't compile. it wouldn't work. Class' implementation of the method function must tak= e=20 _everything_ that Interface's method function can take, and it doesn't = in your=20 example. - Jonathan M Davis
Aug 29 2011
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Tuesday, August 30, 2011 12:42:04 Mariusz Gliwi=C5=84ski wrote:
 Jonathan M Davis wrote:
 On Tuesday, August 30, 2011 08:57:53 Mariusz Gliwi=C5=84ski wrote:
[...]

 <code>
 interface Interface
 {
 void method(Interface);
 }
 class Class : Interface
 {
 void method(Class) {}
 }
=20
 void main() {}
 </code>

This particular example is not a bug. [...]

You're absolutely right, it's not symetric. Now i have to think a bit=

 because i highly relied on this. I'm sorry for taking Your time.

Just so long as you learn, it's not a waste of my time. - Jonathan M Davis
Aug 30 2011
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Mon, 29 Aug 2011 16:24:46 -0400, Jonathan M Davis <jmdavisProg gmx.co=
m>  =

wrote:

 On Monday, August 29, 2011 14:09 Mariusz Gliwi=C5=84ski wrote:
 <code>
 interface Interface {
 Interface method();
 }
 class Class : Interface {
 override Class method() {}
 }
 </code>

 DMD complains it isn't overriding. How should it be according to
 specification, and how about making it legal?

It's _not_ overriding. It's implementing an interface method. Those ar=

 two
 totally different things. And I think that it's horrible that Java  =

 considers
 implementing an interface method as overriding it. I'd _hate_ to see  =

 that in
 D.

Then this must be a bug? interface I { void foo(); } class C : I { override void foo(); // compiles } I feel override should be *allowed* when implementing interface function= s = (but not required). Otherwise, you get into situations where a base cla= ss = decides to become abstract (doesn't implement a function), but a derived= = class is specifying override (especially if override is required, as is = = planned), if that's a compiler error, I think it's a useless error. -Steve
Aug 30 2011
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Tuesday, August 30, 2011 06:47:03 Steven Schveighoffer wrote:
 On Mon, 29 Aug 2011 16:24:46 -0400, Jonathan M Davis <jmdavisProg gmx=

=20
 wrote:
 On Monday, August 29, 2011 14:09 Mariusz Gliwi=C5=84ski wrote:
 <code>
 interface Interface {
 Interface method();
 }
 class Class : Interface {
 override Class method() {}
 }
 </code>
=20
 DMD complains it isn't overriding. How should it be according to
 specification, and how about making it legal?

It's _not_ overriding. It's implementing an interface method. Those=


 two
 totally different things. And I think that it's horrible that Java
 considers
 implementing an interface method as overriding it. I'd _hate_ to se=


 that in
 D.

Then this must be a bug? =20 interface I { void foo(); } =20 class C : I { override void foo(); // compiles } =20 I feel override should be *allowed* when implementing interface funct=

 (but not required).  Otherwise, you get into situations where a base =

 decides to become abstract (doesn't implement a function), but a deri=

 class is specifying override (especially if override is required, as =

 planned), if that's a compiler error, I think it's a useless error.

I think that override belongs on functions which actually override base= class=20 functions. It should be required when a function overrides a base class= =20 function, and it should be disallowed when it's on a function that does= n't=20 override a base class function. Interfaces have nothing to do with it. The whole point of override is to make sure that you know when your fun= ction=20 is or isn't overriding a base class function. Ff the base class changes= , then=20 that's extremely relevant to the derived class, and it _should_ error o= ut if=20 the function is no longer marked as it should be (be it that it has ove= rride=20 when it shouldn't or that it doesn't have it when it should). That way,= you=20 never have functions which override when you didn't mean them to (e.g. = if a=20 new function were added to one of its base classes), and you never have= a=20 function which _doesn't_ override when you mean it to (e.g. when a func= tion=20 was removed from one or more of its base classes). - Jonathan M Davis
Aug 30 2011
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 30 Aug 2011 07:04:27 -0400, Jonathan M Davis <jmdavisProg gmx.co=
m>  =

wrote:

 On Tuesday, August 30, 2011 06:47:03 Steven Schveighoffer wrote:
 On Mon, 29 Aug 2011 16:24:46 -0400, Jonathan M Davis  =


 <jmdavisProg gmx.com>

 wrote:
 On Monday, August 29, 2011 14:09 Mariusz Gliwi=C5=84ski wrote:
 <code>
 interface Interface {
 Interface method();
 }
 class Class : Interface {
 override Class method() {}
 }
 </code>

 DMD complains it isn't overriding. How should it be according to
 specification, and how about making it legal?

It's _not_ overriding. It's implementing an interface method. Those=



 are
 two
 totally different things. And I think that it's horrible that Java
 considers
 implementing an interface method as overriding it. I'd _hate_ to se=



 that in
 D.

Then this must be a bug? interface I { void foo(); } class C : I { override void foo(); // compiles } I feel override should be *allowed* when implementing interface =


 functions
 (but not required).  Otherwise, you get into situations where a base =


 class
 decides to become abstract (doesn't implement a function), but a deri=


 class is specifying override (especially if override is required, as =


 planned), if that's a compiler error, I think it's a useless error.

I think that override belongs on functions which actually override bas=

 class
 functions. It should be required when a function overrides a base clas=

 function, and it should be disallowed when it's on a function that  =

 doesn't
 override a base class function. Interfaces have nothing to do with it.=

 The whole point of override is to make sure that you know when your  =

 function
 is or isn't overriding a base class function. Ff the base class change=

 then
 that's extremely relevant to the derived class, and it _should_ error =

 out if
 the function is no longer marked as it should be (be it that it has  =

 override
 when it shouldn't or that it doesn't have it when it should). That way=

 you
 never have functions which override when you didn't mean them to (e.g.=

 if a
 new function were added to one of its base classes), and you never hav=

 function which _doesn't_ override when you mean it to (e.g. when a  =

 function
 was removed from one or more of its base classes).

This argument has holes in it: class A { void foo(); } class B : A { version(newlyAddedBFoo) override void foo(); } class C : B { override void foo(); // does not see newly added B.foo } This will compile fine with or without the version enabled. When you sa= y = override, you say "I don't care what came before me, I'm implementing th= is = function." Now, if B decided to make foo final, yeah, you should know = about it. But I don't see why override shouldn't simply work when = overriding a not-yet-implemented function. What about an abstract base method, should override be required? class A { void foo() {} abstract void foo2(); } class B : A { override void foo() {} override void foo2() {} // should override be rejected here? What = utility would an error give you? } At the end of the day, an interface is simply a completely abstract = class. It might even have some implementation via final or template = functions, but it participates in virtual functions much the same way as= = classes do. -Steve
Aug 30 2011
prev sibling next sibling parent "Marco Leise" <Marco.Leise gmx.de> writes:
Am 29.08.2011, 22:24 Uhr, schrieb Jonathan M Davis <jmdavisProg gmx.com>:

 It's _not_ overriding. It's implementing an interface method. Those are  
 two
 totally different things. And I think that it's horrible that Java  
 considers
 implementing an interface method as overriding it. I'd _hate_ to see  
 that in
 D.

 - Jonathan M Davis

This design decision in Java isn't particularly bad I think. Look at how dim the line is between an interface, an abstract class and a class. Some languages use the notion of a fully abstract class for interfaces. In case you implement one interface and it is somewhat internal you may choose to provide some default implementations and turn it into an abstract class. At this point you should add 'override' to the all descendant classes that override these implementations. If override was mandatory you could easily spot any methods that correspond to something higher in the hierarchy (extended class / interface). What would you argue for when you implement a method of an abstract class for example? Does it override or implement? But D is not Java and there are already cases of implicit interfaces (Range). So it makes sense not to be overly verbose with interfaces in D. - Marco
Aug 30 2011
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 30 Aug 2011 08:26:17 -0400, Andrei Alexandrescu  
<SeeWebsiteForEmail erdani.org> wrote:

 On 08/30/2011 07:13 AM, Timon Gehr wrote:
 If there already is an implementation, it overrides it, otherwise it
 implements it.

That's pretty much it. The entire purpose of the "override" keyword is to prevent silent bugs of two kinds: (a) User thinks she hooks a specific method but instead introduces a new one. (b) User thinks she introduces a new method but instead hooks one. Override helps only in cases where otherwise a silent error would occur. If the compiler issues an error message without the help of override, override is unneeded and illegal. This is the case with interface and abstract methods - "override" is emphatically unneeded because the compiler/linker wouldn't allow the code anyway.

Your (a) and (b) points seem to be pointing to a different conclusion -- that override should be required for interface methods. Since implementing an interface method does not introduce a new method, it hooks the interface's existing one. I personally think override should be required if it overrides an existing implementation, be rejected if it introduces a completely new symbol, and be optional if it implements an abstract method. The latter rule is purely for code maintenance. 99%, no wait, I think 100% of the time, when a previously abstract base method grows an implementation after you have implemented it in a derived method, the remedy is simply adding override. This feels like annoyance that can be avoided by just putting override on it to begin with. I can't think of a single case where I've implemented a function I *know* is callable by some base class symbol that I'd want to be informed when a base class implements it later on. I don't care, I'm overriding it, no matter what the base class does (unless of course, the base class marks it final, but that would be an error anyways). If the rule must be require or reject, I'd prefer requirement, even for interface methods. -Steve
Aug 30 2011
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 30 Aug 2011 11:58:43 -0400, Timon Gehr <timon.gehr gmx.ch> wrote:

 On 08/30/2011 05:49 PM, Christophe wrote:
 The fact that the code compile only if all interface methods are
 implemented does not imply that the programmer knows which method he
 implemented hooks and which does not.

interface I{ void method(); } class C: I{ void method() {} // not a hook. }

Why not? All a "hook" is is adding an entry into a base class' vtable. This is no different, it's just the base "class" is an interface. -Steve
Aug 30 2011
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 30 Aug 2011 11:40:40 -0400, Andrei Alexandrescu  
<SeeWebsiteForEmail erdani.org> wrote:

 On 8/30/11 7:45 AM, Steven Schveighoffer wrote:
 On Tue, 30 Aug 2011 08:26:17 -0400, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:

 On 08/30/2011 07:13 AM, Timon Gehr wrote:
 If there already is an implementation, it overrides it, otherwise it
 implements it.

That's pretty much it. The entire purpose of the "override" keyword is to prevent silent bugs of two kinds: (a) User thinks she hooks a specific method but instead introduces a new one. (b) User thinks she introduces a new method but instead hooks one. Override helps only in cases where otherwise a silent error would occur. If the compiler issues an error message without the help of override, override is unneeded and illegal. This is the case with interface and abstract methods - "override" is emphatically unneeded because the compiler/linker wouldn't allow the code anyway.

Your (a) and (b) points seem to be pointing to a different conclusion -- that override should be required for interface methods.

No, because the compiler rejects code that doesn't implement all methods of an interface.

When I write code that derives from a base class, I'm declaring with override that I want to implement the base class' function. When I write code that implements an interface, I'm declaring with override that I want to implement the interface's function. I.e. I think I'm hooking a specific method, and not introducing a new one. If override isn't required, wouldn't the lack of (b) mean you can get a silent bug when altering an interface? For example: interface I { } class C : I { void foo() {} // written expecting that I'm not hooking anything. } Now I is altered to say: interface I { void foo() {} // which is described as doing something completely different than C.foo } -Steve
Aug 30 2011
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 30 Aug 2011 12:18:32 -0400, Timon Gehr <timon.gehr gmx.ch> wrote:

 On 08/30/2011 06:00 PM, Steven Schveighoffer wrote:
 On Tue, 30 Aug 2011 11:58:43 -0400, Timon Gehr <timon.gehr gmx.ch>  
 wrote:

 On 08/30/2011 05:49 PM, Christophe wrote:
 The fact that the code compile only if all interface methods are
 implemented does not imply that the programmer knows which method he
 implemented hooks and which does not.

interface I{ void method(); } class C: I{ void method() {} // not a hook. }

Why not? All a "hook" is is adding an entry into a base class' vtable. This is no different, it's just the base "class" is an interface. -Steve

As far as I can tell, a hook is overwriting an existing entry.

Nothing is "overwritten", what's written into the table is decided at compile-time. -Steve
Aug 30 2011
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 30 Aug 2011 12:29:59 -0400, Andrei Alexandrescu  
<SeeWebsiteForEmail erdani.org> wrote:

 On 8/30/11 11:06 AM, Steven Schveighoffer wrote:
 When I write code that derives from a base class, I'm declaring with
 override that I want to implement the base class' function.
 When I write code that implements an interface, I'm declaring with
 override that I want to implement the interface's function.

From the cycle "deadpan answers": I think one should use "override" when one wants to override.

Then your description of cases where override helps prevent bugs should reflect that: (a) User thinks she overrides a specific method but instead introduces a new one. (b) User thinks she introduces a new method but instead overrides one. I consider implementing an interface method to be hooking, since you are hooking calls from said interface. I guess if we want to avoid solving all hooking problems, even those where one does not intend to implement an interface, but accidentally does, or introduce large annoyances where someone changes a widely used interface to an abstract class, then I guess the status quo is good. -Steve
Aug 30 2011
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 30 Aug 2011 12:55:30 -0400, Timon Gehr <timon.gehr gmx.ch> wrote:

 On 08/30/2011 06:23 PM, Steven Schveighoffer wrote:
 On Tue, 30 Aug 2011 12:18:32 -0400, Timon Gehr <timon.gehr gmx.ch>  
 wrote:

 On 08/30/2011 06:00 PM, Steven Schveighoffer wrote:
 On Tue, 30 Aug 2011 11:58:43 -0400, Timon Gehr <timon.gehr gmx.ch>
 wrote:

 On 08/30/2011 05:49 PM, Christophe wrote:
 The fact that the code compile only if all interface methods are
 implemented does not imply that the programmer knows which method he
 implemented hooks and which does not.

interface I{ void method(); } class C: I{ void method() {} // not a hook. }

Why not? All a "hook" is is adding an entry into a base class' vtable. This is no different, it's just the base "class" is an interface. -Steve

As far as I can tell, a hook is overwriting an existing entry.

Nothing is "overwritten", what's written into the table is decided at compile-time. -Steve

It is conceptually "overwritten" at compile time: Copy vtable from parent and replace the overriden entries.

And that's no different from implementing an interface, or an abstract class that does not implement an interface completely -- copy the vtable and overwrite the entries.
 And I am quite certain that what exactly is in the table is actually  
 decided at link time.

The vtable's contents are known at compile time, however, they may not be resolved until link time. But they are not set to one method and then "overwritten" by another at link time, they are filled with symbols known at compile time, and then the symbols are resolved at link time. -Steve
Aug 30 2011
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 30 Aug 2011 13:06:02 -0400, Timon Gehr <timon.gehr gmx.ch> wrote:

 On 08/30/2011 06:43 PM, Steven Schveighoffer wrote:
 On Tue, 30 Aug 2011 12:29:59 -0400, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:

 On 8/30/11 11:06 AM, Steven Schveighoffer wrote:
 When I write code that derives from a base class, I'm declaring with
 override that I want to implement the base class' function.
 When I write code that implements an interface, I'm declaring with
 override that I want to implement the interface's function.

From the cycle "deadpan answers": I think one should use "override" when one wants to override.

Then your description of cases where override helps prevent bugs should reflect that: (a) User thinks she overrides a specific method but instead introduces a new one. (b) User thinks she introduces a new method but instead overrides one. I consider implementing an interface method to be hooking, since you are hooking calls from said interface. I guess if we want to avoid solving all hooking problems, even those where one does not intend to implement an interface, but accidentally does, or introduce large annoyances where someone changes a widely used interface to an abstract class, then I guess the status quo is good. -Steve

I don't think that you can change a widely used interface into an abstract class and not introduce annoyances much larger than override is capable of creating.

interface I { int foo(); void bar(); } -> interface _I { int foo(); void bar(); } abstract class I : _I { int foo() { return 0; } } Now, everywhere I was implemented before has to change all their implementations of foo() to override, just to compile. There may be some cases where classes already had a base class, but it depends on the context of where I is implemented. However, in 100% of the cases, putting override on each implementation of foo does *not* result in a bug. My point is, what "bug" is it preventing by rejecting override when implementing an interface? The only "bug" I see is that you didn't put override in the signature. That translates to an annoyance, not a real bug.
 How does the status quo prevent implementing interface methods by  
 accident?

It doesn't. That was my point. -Steve
Aug 30 2011
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 30 Aug 2011 13:16:58 -0400, Steven Schveighoffer  
<schveiguy yahoo.com> wrote:

 On Tue, 30 Aug 2011 13:06:02 -0400, Timon Gehr <timon.gehr gmx.ch> wrote:

 I don't think that you can change a widely used interface into an  
 abstract class and not introduce annoyances much larger than override  
 is capable of creating.

interface I { int foo(); void bar(); } -> interface _I { int foo(); void bar(); } abstract class I : _I { int foo() { return 0; } }

That was kind of weird, I guess I should have done: interface I { int foo(); void bar(); } -> abstract class I { int foo() { return 0; } void bar(); } -Steve
Aug 30 2011
prev sibling next sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Tuesday, August 30, 2011 10:06 Timon Gehr wrote:
 On 08/30/2011 06:43 PM, Steven Schveighoffer wrote:
 On Tue, 30 Aug 2011 12:29:59 -0400, Andrei Alexandrescu
 
 <SeeWebsiteForEmail erdani.org> wrote:
 On 8/30/11 11:06 AM, Steven Schveighoffer wrote:
 When I write code that derives from a base class, I'm declaring with
 override that I want to implement the base class' function.
 When I write code that implements an interface, I'm declaring with
 override that I want to implement the interface's function.

From the cycle "deadpan answers": I think one should use "override" when one wants to override.

Then your description of cases where override helps prevent bugs should reflect that: (a) User thinks she overrides a specific method but instead introduces a new one. (b) User thinks she introduces a new method but instead overrides one. I consider implementing an interface method to be hooking, since you are hooking calls from said interface. I guess if we want to avoid solving all hooking problems, even those where one does not intend to implement an interface, but accidentally does, or introduce large annoyances where someone changes a widely used interface to an abstract class, then I guess the status quo is good. -Steve

I don't think that you can change a widely used interface into an abstract class and not introduce annoyances much larger than override is capable of creating. How does the status quo prevent implementing interface methods by accident?

If the class doesn't claim that it's implmenting the interface, then it's a non-issue. You have to declare it to be implementing the interface (or one of its base classes must be declared to implement it) for it to be usable as that interface. If you declare a base class to implement an interface, then that base class must either delare or implement all of the functions in the interface. Any function which a derived class might implement is going to need override (assuming that you compile with -w), since it would be overriding the base class' function. If you declare a derived class to implement an interface, then that class must declare or implement all of the functions in the interface. Any function in a base class which happens to match an interface function won't count towards implementing the interface (not even with alias apparently - I don't know if that's a bug or not). So, it would have to be declared in the derived class, and (assuming that you compile with -w) override would catch the fact that a base class happened to implement the same function. But even without override, you can't use the base class as the interface anyway, so the fact that the derived class must declare or implement all of the interface's functions itself means that a base class implementation won't accidentally count as implementing an interface function. The _only_ case where you can accidentally implement an interface function is if you have a function in the class which is supposed to be implementing the interface which happens to implement an interface function, and you didn't notice - that is, you declared the function previously, added the fact that the class implements an interface, forgot to make the class properly implement one of the interface's functions, the existing function matches the interface function that you missed, and you don't notice. That's not a particularly likely scenario unless you have ridiculously large class or are doing something with mixins. So, "accidentally" implementing an interface function isn't really an issue. - Jonathan M Davis
Aug 30 2011
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 30 Aug 2011 13:21:09 -0400, Timon Gehr <timon.gehr gmx.ch> wrote:

 On 08/30/2011 07:06 PM, Steven Schveighoffer wrote:
 On Tue, 30 Aug 2011 12:55:30 -0400, Timon Gehr <timon.gehr gmx.ch>  
 wrote:

 On 08/30/2011 06:23 PM, Steven Schveighoffer wrote:
 On Tue, 30 Aug 2011 12:18:32 -0400, Timon Gehr <timon.gehr gmx.ch>
 wrote:

 On 08/30/2011 06:00 PM, Steven Schveighoffer wrote:
 On Tue, 30 Aug 2011 11:58:43 -0400, Timon Gehr <timon.gehr gmx.ch>
 wrote:

 On 08/30/2011 05:49 PM, Christophe wrote:
 The fact that the code compile only if all interface methods are
 implemented does not imply that the programmer knows which method  
 he
 implemented hooks and which does not.

interface I{ void method(); } class C: I{ void method() {} // not a hook. }

Why not? All a "hook" is is adding an entry into a base class' vtable. This is no different, it's just the base "class" is an interface. -Steve

As far as I can tell, a hook is overwriting an existing entry.

Nothing is "overwritten", what's written into the table is decided at compile-time. -Steve

It is conceptually "overwritten" at compile time: Copy vtable from parent and replace the overriden entries.

And that's no different from implementing an interface, or an abstract class that does not implement an interface completely -- copy the vtable and overwrite the entries.

interfaces don't possess an own vtable. It is created from scratch for each class implementing the interface.

The vtable for the interface is identical in layout for each class implementing it. So if foo() lives at index 0 in the function table for class C, it lives at index 0 for class D as well. Otherwise, polymorphism wouldn't work, and neither would delegates to interfaces. When you call an interface function, the thunk subtracting the offset to get to the class pointer is done by a pre-function code piece, then the real function is jumped to. So yes, each interface has its own vtable layout, similar to how an abstract class with no implementations would have its own vtable, even though it's not instantiable. -Steve
Aug 30 2011
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 30 Aug 2011 13:39:35 -0400, Timon Gehr <timon.gehr gmx.ch> wrote:

 On 08/30/2011 07:16 PM, Steven Schveighoffer wrote:
 On Tue, 30 Aug 2011 13:06:02 -0400, Timon Gehr <timon.gehr gmx.ch>  
 wrote:

 On 08/30/2011 06:43 PM, Steven Schveighoffer wrote:
 On Tue, 30 Aug 2011 12:29:59 -0400, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:

 On 8/30/11 11:06 AM, Steven Schveighoffer wrote:
 When I write code that derives from a base class, I'm declaring with
 override that I want to implement the base class' function.
 When I write code that implements an interface, I'm declaring with
 override that I want to implement the interface's function.

From the cycle "deadpan answers": I think one should use "override" when one wants to override.

Then your description of cases where override helps prevent bugs should reflect that: (a) User thinks she overrides a specific method but instead introduces a new one. (b) User thinks she introduces a new method but instead overrides one. I consider implementing an interface method to be hooking, since you are hooking calls from said interface. I guess if we want to avoid solving all hooking problems, even those where one does not intend to implement an interface, but accidentally does, or introduce large annoyances where someone changes a widely used interface to an abstract class, then I guess the status quo is good. -Steve

I don't think that you can change a widely used interface into an abstract class and not introduce annoyances much larger than override is capable of creating.

interface I { int foo(); void bar(); } -> interface _I { int foo(); void bar(); } abstract class I : _I { int foo() { return 0; } } Now, everywhere I was implemented before has to change all their implementations of foo() to override, just to compile. There may be some cases where classes already had a base class, but it depends on the context of where I is implemented.

That is what I meant.

I know. What I'm saying is it's feasible for the nature of an interface to be such that you don't have inheritance chains of more than one class. Typically a change like this is done for entire libraries where one person is in control of all the implementing classes, and the author knows the interface to abstract class change will not be a burden. Technically, the problems created would make such a change not feasible, not just annoying. I'm talking about cases where it is feasible.
 My point is, what "bug" is it preventing by rejecting override when
 implementing an interface? The only "bug" I see is that you didn't put
 override in the signature. That translates to an annoyance, not a real  
 bug.

This one: interface I{ void method1(); void method2(); void method3(); } class C: I{ override void method1(){ ... } override void method2(){ ... } override void method3(){ ... } } => // refactoring implementations of I in C to abstract class D interface I{ void method1(); void method2(); void method3(); } abstract class D: I{ override void method1(){ ... } override void method2(){ ... } override void method3(){ ... } } class C: D{ // left method2() inside class C by accident override void method2(){ ... } // override makes compiler shut up }

We could find cases like this all day. Make I a class, and this problem also occurs. Without the compiler having access to the *changes* it cannot be perfect in detecting refactoring errors. -Steve
Aug 30 2011
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 30 Aug 2011 14:27:25 -0400, Timon Gehr <timon.gehr gmx.ch> wrote:

 What I was saying is not that there is no specific layout, just that an  
 interface by itself does not need to be represented in the object file.  
 All interface vtbls are part of the classinfo of the implementing  
 classes.

 in

 interface I{
      void method();
 }
 class C: I{
      void method(){}
 }

 No overriding of an existing implementation is taking place, the  
 interface inheritance creates a new interface vtable.

OK I really can't continue this :) The details we are discussing are abstractly defined in the compiler, and really should have no place in whether something is a 'hook' or not. It really just depends on how you look at it. -Steve
Aug 30 2011
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 30 Aug 2011 14:30:42 -0400, Timon Gehr <timon.gehr gmx.ch> wrote:

 On 08/30/2011 07:50 PM, Steven Schveighoffer wrote:
 We could find cases like this all day.

 Make I a class, and this problem also occurs.

 Without the compiler having access to the *changes* it cannot be perfect
 in detecting refactoring errors.

 -Steve

Chances are that it will detect more errors if "override" actually means override.

Is it just the name? What if it was implement? or override_or_implement? Would that make it "detect more errors"? I can't see how finding more bugs is a bad thing, regardless of what the name of the keyword is. -Steve
Aug 30 2011
prev sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 30 Aug 2011 14:56:46 -0400, Timon Gehr <timon.gehr gmx.ch> wrote:

 On 08/30/2011 08:35 PM, Steven Schveighoffer wrote:
 On Tue, 30 Aug 2011 14:30:42 -0400, Timon Gehr <timon.gehr gmx.ch>  
 wrote:

 On 08/30/2011 07:50 PM, Steven Schveighoffer wrote:
 We could find cases like this all day.

 Make I a class, and this problem also occurs.

 Without the compiler having access to the *changes* it cannot be  
 perfect
 in detecting refactoring errors.

 -Steve

Chances are that it will detect more errors if "override" actually means override.

Is it just the name? What if it was implement? or override_or_implement? Would that make it "detect more errors"?

I am saying: override_or_implement naturally will detect less errors because it is less specific. Based on context it either means "do nothing special" or "override that method". (that is the current behavior of "override" of course) Renaming the keyword would make its current meaning more explicit, it wouldn't make it detect more errors.

I mean if override was required for reimplementing base class functions and required for implementing interface functions. The errors it doesn't detect is when an interface changes to a class, and for some reason you no longer want to override, um... I have no idea what errors it wouldn't detect. -Steve
Aug 30 2011