digitalmars.D - When does final mean "maybe, kinda, sorta" ?
- kris (53/53) Jan 22 2007 "That's a great deal to make one word mean," Alice said in a thoughtful
- Andrei Alexandrescu (See Website For Email) (6/10) Jan 22 2007 I agree about the misleading part, but I don't think that overriding
- kris (3/17) Jan 22 2007 Good point. With D, however, the override itself would probably have to
- Sean Kelly (8/18) Jan 22 2007 It's a good design approach, but there's no reason the virtual methods
- Andrei Alexandrescu (See Website For Email) (9/27) Jan 22 2007 There is a big difference between private and protected. Private means
- Sean Kelly (20/48) Jan 22 2007 But you can call it, or even change its visibility:
- Andrei Alexandrescu (See Website For Email) (4/52) Jan 23 2007 Oh, my hope was that D disallows republicizing private functions :o(.
- Sean Kelly (4/57) Jan 23 2007 I think it effectively does, since private functions can not be
- Andrei Alexandrescu (See Website For Email) (4/26) Jan 23 2007 That's great news. The semicolons should have informed me... oh, and
- Frits van Bommel (3/29) Jan 23 2007 And there's definitely no '= 0' at the end of method declarations. Oh,
- John Reimer (3/6) Jan 23 2007 Yeah! Rub it in... lol! :D
- kris (3/10) Jan 22 2007 Design philosophy aside, what should be done about the issues with
- Sean Kelly (7/18) Jan 23 2007 I think the current design is consistent but potentially confusing. If
- kris (5/30) Jan 23 2007 Fair enough. Then the compiler should be a tad smarter about disallowing...
- Sean Kelly (3/31) Jan 23 2007 The spec does this in a number of places. For example:
- Steve Horne (39/44) Jan 22 2007 Having been in C++ mode for a bit, I'm probably misunderstanding the
- kris (6/10) Jan 23 2007 Given that, I'd imagine you'd be a proponent of making 'override' a
- Steve Horne (50/60) Jan 23 2007 Override should only be specified when the intent is to override, IMO.
- kris (7/39) Jan 23 2007 [snip]
- Steve Horne (9/16) Jan 24 2007 Ah - ok. I'm not so sure the override modifier has much value, done
"That's a great deal to make one word mean," Alice said in a thoughtful tone. "When I make a word do a lot of work like that," said Humpty Dumpty, "I always pay it extra." Reading one of Andrei's posts about const and final reminded me of what I consider to be a D wart. This is taken directly from the D reference manual: "Functions marked as final may not be overridden in a derived class, unless they are also private." Just how much does "final" get paid for this? Onto the given example: <quote> class A { int def() { ... } final int foo() { ... } final private int bar() { ... } private int abc() { ... } } class B : A { int def() { ... } // ok, overrides A.def int foo() { ... } // error, A.foo is final int bar() { ... } // ok, A.bar is final private, but not virtual int abc() { ... } // ok, A.abc is not virtual, B.abc is virtual } void test(A a) { a.def(); // calls B.def a.foo(); // calls A.foo a.bar(); // calls A.bar a.abc(); // calls A.abc } void func() { B b = new B(); test(b); } </quote> 1) You had to read that at least twice, didn't you? :) 2) Seems to me the usage of "final" here is entirely misleading, and opens up a lurking hole for some poor sod to break their ankle in. 3) the example (from the ref manual) highlights overriding of private and private-final methods. Surely this applies only within module scope? That is, within the same module? Assuming that's the case, why would any sane engineer do such a thing instead of changing the original class code? They have the source, obviously, and overriding private seems quite dubious at best. I can think of one case, but can't see why the language would need to support it explicitly. In short, it appears the example exhibits some poor practice (overriding private methods), is somewhat misleading (one certainly *hopes* private cannot be seen beyond module-scope), and discusses how to make "final" mean something quite other than final. How about fixing final? Or name it something more appropriate? It really shouldn't get paid any more than other keywords ... - Kris
Jan 22 2007
kris wrote: [snip]In short, it appears the example exhibits some poor practice (overriding private methods), is somewhat misleading (one certainly *hopes* private cannot be seen beyond module-scope), and discusses how to make "final" mean something quite other than final.I agree about the misleading part, but I don't think that overriding private methods is poor practice. In fact I think it's rich practice :o). See e.g. http://www.gotw.ca/publications/mill18.htm. Andrei
Jan 22 2007
Andrei Alexandrescu (See Website For Email) wrote:kris wrote: [snip]Good point. With D, however, the override itself would probably have to be within the same module as the Template Method?In short, it appears the example exhibits some poor practice (overriding private methods), is somewhat misleading (one certainly *hopes* private cannot be seen beyond module-scope), and discusses how to make "final" mean something quite other than final.I agree about the misleading part, but I don't think that overriding private methods is poor practice. In fact I think it's rich practice :o). See e.g. http://www.gotw.ca/publications/mill18.htm. Andrei
Jan 22 2007
Andrei Alexandrescu (See Website For Email) wrote:kris wrote: [snip]It's a good design approach, but there's no reason the virtual methods must be private--they could be protected as well. One could argue that the design is cleaner with the virtual methods private, but since the methods must be overridden by the derived class it's not like any protection attributes are being maintained anyway. Isn't this a current topic of discussion on comp.l.c++.m? :-) SeanIn short, it appears the example exhibits some poor practice (overriding private methods), is somewhat misleading (one certainly *hopes* private cannot be seen beyond module-scope), and discusses how to make "final" mean something quite other than final.I agree about the misleading part, but I don't think that overriding private methods is poor practice. In fact I think it's rich practice :o). See e.g. http://www.gotw.ca/publications/mill18.htm.
Jan 22 2007
Sean Kelly wrote:Andrei Alexandrescu (See Website For Email) wrote:There is a big difference between private and protected. Private means that later-added code cannot call the method, period. It could be said that private is "distantly more private" than both protected and public because both of the latter allow access by unbounded amounts of code. So there is indeed something interesting by being required to implement something that you're not allowed to call. Something like Shirley Temple acting in movies she was too young to be allowed to watch :o). Andreikris wrote: [snip]It's a good design approach, but there's no reason the virtual methods must be private--they could be protected as well. One could argue that the design is cleaner with the virtual methods private, but since the methods must be overridden by the derived class it's not like any protection attributes are being maintained anyway. Isn't this a current topic of discussion on comp.l.c++.m? :-)In short, it appears the example exhibits some poor practice (overriding private methods), is somewhat misleading (one certainly *hopes* private cannot be seen beyond module-scope), and discusses how to make "final" mean something quite other than final.I agree about the misleading part, but I don't think that overriding private methods is poor practice. In fact I think it's rich practice :o). See e.g. http://www.gotw.ca/publications/mill18.htm.
Jan 22 2007
Andrei Alexandrescu (See Website For Email) wrote:Sean Kelly wrote:But you can call it, or even change its visibility: class Base { private: virtual void fn() = 0; }; class Derived : Base { public: virtual void fn() {} void call() { fn(); } }; Sure, you can't call it through Base::fn(), but... :-) I'll admit it's a clever design pattern, and one I use myself in C++, but I think there is also value in privates being implicitly final as in D. No expressive power is really lost--the methods could be made protected just as easily--and I think it actually makes more conceptual sense that private functions cannot be overridden. SeanAndrei Alexandrescu (See Website For Email) wrote:There is a big difference between private and protected. Private means that later-added code cannot call the method, period. It could be said that private is "distantly more private" than both protected and public because both of the latter allow access by unbounded amounts of code. So there is indeed something interesting by being required to implement something that you're not allowed to call. Something like Shirley Temple acting in movies she was too young to be allowed to watch :o).kris wrote: [snip]It's a good design approach, but there's no reason the virtual methods must be private--they could be protected as well. One could argue that the design is cleaner with the virtual methods private, but since the methods must be overridden by the derived class it's not like any protection attributes are being maintained anyway. Isn't this a current topic of discussion on comp.l.c++.m? :-)In short, it appears the example exhibits some poor practice (overriding private methods), is somewhat misleading (one certainly *hopes* private cannot be seen beyond module-scope), and discusses how to make "final" mean something quite other than final.I agree about the misleading part, but I don't think that overriding private methods is poor practice. In fact I think it's rich practice :o). See e.g. http://www.gotw.ca/publications/mill18.htm.
Jan 22 2007
Sean Kelly wrote:Andrei Alexandrescu (See Website For Email) wrote:Oh, my hope was that D disallows republicizing private functions :o(. Spectacular failure to provide a great feature... AndreiSean Kelly wrote:But you can call it, or even change its visibility: class Base { private: virtual void fn() = 0; }; class Derived : Base { public: virtual void fn() {} void call() { fn(); } }; Sure, you can't call it through Base::fn(), but... :-)Andrei Alexandrescu (See Website For Email) wrote:There is a big difference between private and protected. Private means that later-added code cannot call the method, period. It could be said that private is "distantly more private" than both protected and public because both of the latter allow access by unbounded amounts of code. So there is indeed something interesting by being required to implement something that you're not allowed to call. Something like Shirley Temple acting in movies she was too young to be allowed to watch :o).kris wrote: [snip]It's a good design approach, but there's no reason the virtual methods must be private--they could be protected as well. One could argue that the design is cleaner with the virtual methods private, but since the methods must be overridden by the derived class it's not like any protection attributes are being maintained anyway. Isn't this a current topic of discussion on comp.l.c++.m? :-)In short, it appears the example exhibits some poor practice (overriding private methods), is somewhat misleading (one certainly *hopes* private cannot be seen beyond module-scope), and discusses how to make "final" mean something quite other than final.I agree about the misleading part, but I don't think that overriding private methods is poor practice. In fact I think it's rich practice :o). See e.g. http://www.gotw.ca/publications/mill18.htm.
Jan 23 2007
Andrei Alexandrescu (See Website For Email) wrote:Sean Kelly wrote:I think it effectively does, since private functions can not be overridden. The above was C++ (I should have labeled the code). SeanAndrei Alexandrescu (See Website For Email) wrote:Oh, my hope was that D disallows republicizing private functions :o(. Spectacular failure to provide a great feature...Sean Kelly wrote:But you can call it, or even change its visibility: class Base { private: virtual void fn() = 0; }; class Derived : Base { public: virtual void fn() {} void call() { fn(); } }; Sure, you can't call it through Base::fn(), but... :-)Andrei Alexandrescu (See Website For Email) wrote:There is a big difference between private and protected. Private means that later-added code cannot call the method, period. It could be said that private is "distantly more private" than both protected and public because both of the latter allow access by unbounded amounts of code. So there is indeed something interesting by being required to implement something that you're not allowed to call. Something like Shirley Temple acting in movies she was too young to be allowed to watch :o).kris wrote: [snip]It's a good design approach, but there's no reason the virtual methods must be private--they could be protected as well. One could argue that the design is cleaner with the virtual methods private, but since the methods must be overridden by the derived class it's not like any protection attributes are being maintained anyway. Isn't this a current topic of discussion on comp.l.c++.m? :-)In short, it appears the example exhibits some poor practice (overriding private methods), is somewhat misleading (one certainly *hopes* private cannot be seen beyond module-scope), and discusses how to make "final" mean something quite other than final.I agree about the misleading part, but I don't think that overriding private methods is poor practice. In fact I think it's rich practice :o). See e.g. http://www.gotw.ca/publications/mill18.htm.
Jan 23 2007
Sean Kelly wrote:Andrei Alexandrescu (See Website For Email) wrote:That's great news. The semicolons should have informed me... oh, and wait, there's no "virtual" in D... :o) AndreiSean Kelly wrote:I think it effectively does, since private functions can not be overridden. The above was C++ (I should have labeled the code).class Base { private: virtual void fn() = 0; }; class Derived : Base { public: virtual void fn() {} void call() { fn(); } }; Sure, you can't call it through Base::fn(), but... :-)Oh, my hope was that D disallows republicizing private functions :o(. Spectacular failure to provide a great feature...
Jan 23 2007
Andrei Alexandrescu (See Website For Email) wrote:Sean Kelly wrote:And there's definitely no '= 0' at the end of method declarations. Oh, and his comment at the end mentioned 'Base::fn()' instead of 'Base.fn()' :)Andrei Alexandrescu (See Website For Email) wrote:That's great news. The semicolons should have informed me... oh, and wait, there's no "virtual" in D... :o)Sean Kelly wrote:I think it effectively does, since private functions can not be overridden. The above was C++ (I should have labeled the code).class Base { private: virtual void fn() = 0; }; class Derived : Base { public: virtual void fn() {} void call() { fn(); } }; Sure, you can't call it through Base::fn(), but... :-)Oh, my hope was that D disallows republicizing private functions :o(. Spectacular failure to provide a great feature...
Jan 23 2007
On Tue, 23 Jan 2007 12:08:39 +0100, Frits van Bommel wrote:And there's definitely no '= 0' at the end of method declarations. Oh, and his comment at the end mentioned 'Base::fn()' instead of 'Base.fn()' :)Yeah! Rub it in... lol! :D -JJR
Jan 23 2007
Andrei Alexandrescu (See Website For Email) wrote:kris wrote: [snip] I agree about the misleading part, but I don't think that overriding private methods is poor practice. In fact I think it's rich practice :o). See e.g. http://www.gotw.ca/publications/mill18.htm. AndreiDesign philosophy aside, what should be done about the issues with "final" itself?
Jan 22 2007
kris wrote:Andrei Alexandrescu (See Website For Email) wrote:I think the current design is consistent but potentially confusing. If a function can be virtual (ie. if it is not private) then "final" controls whether it can be overridden. So making a private function final is meaningless because it cannot be overridden--in this case, "final" is simply ignored. Seankris wrote: [snip] I agree about the misleading part, but I don't think that overriding private methods is poor practice. In fact I think it's rich practice :o). See e.g. http://www.gotw.ca/publications/mill18.htm. AndreiDesign philosophy aside, what should be done about the issues with "final" itself?
Jan 23 2007
Sean Kelly wrote:kris wrote:Fair enough. Then the compiler should be a tad smarter about disallowing 'stupid' combinations of attributes. This applies to many other attributes, not just final. People /will/ use whatever combination they're allowed to, and the doc appears to encourage them to do so.Andrei Alexandrescu (See Website For Email) wrote:I think the current design is consistent but potentially confusing. If a function can be virtual (ie. if it is not private) then "final" controls whether it can be overridden. So making a private function final is meaningless because it cannot be overridden--in this case, "final" is simply ignored. Seankris wrote: [snip] I agree about the misleading part, but I don't think that overriding private methods is poor practice. In fact I think it's rich practice :o). See e.g. http://www.gotw.ca/publications/mill18.htm. AndreiDesign philosophy aside, what should be done about the issues with "final" itself?
Jan 23 2007
kris wrote:Sean Kelly wrote:The spec does this in a number of places. For example: const auto static auto const auto i = 5; // what is i?kris wrote:Fair enough. Then the compiler should be a tad smarter about disallowing 'stupid' combinations of attributes. This applies to many other attributes, not just final. People /will/ use whatever combination they're allowed to, and the doc appears to encourage them to do so.Andrei Alexandrescu (See Website For Email) wrote:I think the current design is consistent but potentially confusing. If a function can be virtual (ie. if it is not private) then "final" controls whether it can be overridden. So making a private function final is meaningless because it cannot be overridden--in this case, "final" is simply ignored.kris wrote: [snip] I agree about the misleading part, but I don't think that overriding private methods is poor practice. In fact I think it's rich practice :o). See e.g. http://www.gotw.ca/publications/mill18.htm. AndreiDesign philosophy aside, what should be done about the issues with "final" itself?
Jan 23 2007
On Mon, 22 Jan 2007 15:31:25 -0800, kris <foo bar.com> wrote:"Functions marked as final may not be overridden in a derived class, unless they are also private." Just how much does "final" get paid for this? Onto the given example:...2) Seems to me the usage of "final" here is entirely misleading, and opens up a lurking hole for some poor sod to break their ankle in.Having been in C++ mode for a bit, I'm probably misunderstanding the issue, but for what it's worth... Aren't private members excluded from the virtual table? Early bound, in other words? If so, one way to view it is that private methods cannot be overridden and are therefore inherently final, so it does no particular harm to actually say that they are final. Either requiring 'final' or banning it might help code consistency and readability, but it seems like a minor issue. How can I say that a private method can't be overridden? Well, if there is no late binding, a new method with the same signature isn't really an override. The private method doesn't really exist in any derived classes interface, internal or external. The only reason that derived classes are aware at all is to improve the compiler error messages. So any method added to a derived class with the same signature is just a completely new and independent method - not an override. It's really no different to having a method with the same signature in an unrelated class. Potentially confusing enough to get a note in the documentation, maybe, but do we really want to ban derived classes from using certain method signatures just because they were used for private methods in the base class? That sounds like a violation of encapsulation to me. The derived classes shouldn't need to know about the private members of the base class at all, even for the purposes of avoiding name clashes. And adding a new private member to a base class should not break any derived classes that might happen to already use the same signature for a (private or public) method, especially since you may have no control or even knowledge of those derived classes. Ah! you say, but we're talking about code in the same module. But then we get different rules for whether a derived class can define certain method signatures based on which module it happens to be in. Sure, you can rename the private methods in the base class to avoid a clash if you need to, but without reliable refactoring tools to catch all the calls, that can be potentially error-prone. -- Remove 'wants' and 'nospam' from e-mail.
Jan 22 2007
Steve Horne wrote: [snip]And adding a new private member to a base class should not break any derived classes that might happen to already use the same signature for a (private or public) method, especially since you may have no control or even knowledge of those derived classes.Given that, I'd imagine you'd be a proponent of making 'override' a required keyword? After all, not requiring it will likely lead to the same type of problem when a base-class method is removed. Yet, judging by past record, override is unlikely to ever be required.
Jan 23 2007
On Tue, 23 Jan 2007 00:26:10 -0800, kris <foo bar.com> wrote:Steve Horne wrote: [snip]Override should only be specified when the intent is to override, IMO. If adding a new public/protected method to a base class results in its accidentally being overridden by a pre-existing conflicting derived-class method, clearly that's bad. So... 1. Specifying override on a method that doesn't override any base class method should be an error. 2. Failing to specify override on a method that does override a base class public/protected method should be an error. I thought that was what D does anyway, and for that matter that it was the whole point of the override keyword - but, as I said, I'm more in C++ mode ATM (and haven't been using D that long anyway). Presumably removal of an overridden base-class method would be covered by case 1, which is why you are saying it should be required, and therefore I assume this case 1 error doesn't occur. Which gets a reading on my odd-ometer. Mind you, removing a public/protected interface from a published class should be a pretty unusual thing to do. Getting people dependent on an interface and then just taking it away without warning is more than a bit dodgy. The possibility of problems shouldn't really come as a surprise. It's similar to the rule for COM interfaces - extending is OK, different implementations OK, but compatibility with previously published interfaces should be maintained (though the main breaker of that rule seems to be Microsoft itself). When adding new methods creates problems, there is genuine reason why you wouldn't necessarily anticipate the problems - you can't necessarily know which new method signatures would be safe and which would cause conflicts. So case 2 above is much more important to me than case 1, since it catches non-obvious errors rather than errors I should have anticipated. My main reason for case 1 is that programmers shouldn't add override flags to every single method just to save thinking about it, since it defeats the whole point of the keyword. But it's just so obviously grossly bad style anyway, like not bothering with indentation or calling your variable var1, var2, var3 and so on. Going off on a tangent, a way of saying 'OK, this is the same signature as a base class method, but this is independent, and gets a separate slot in the virtual table' might be a good idea. Perhaps an alternate application of the 'new' keyword. Or maybe there already is a flag for this, and I forgot. The idea is that, when a derived class developer gets a conflict with a new base class interface, there's a quick (if slightly dirty) fix. The derived class can keep its (possibly also published) interface intact. Anyone needing the base class version can use a call notation indicating that, or else cast to the base class - less than ideal, but maybe better than forcing the derived class developers into renaming and refactoring, and the resulting interface change. -- Remove 'wants' and 'nospam' from e-mail.And adding a new private member to a base class should not break any derived classes that might happen to already use the same signature for a (private or public) method, especially since you may have no control or even knowledge of those derived classes.Given that, I'd imagine you'd be a proponent of making 'override' a required keyword? After all, not requiring it will likely lead to the same type of problem when a base-class method is removed. Yet, judging by past record, override is unlikely to ever be required.
Jan 23 2007
Steve Horne wrote:On Tue, 23 Jan 2007 00:26:10 -0800, kris <foo bar.com> wrote:[snip] (1) does generate an error, but (2) has never generated one, and requests to make it do so have met with silence from W for years :) Everything else you say I agree with, and thanks for taking the time to respond in such detail. - KrisSteve Horne wrote: [snip]Override should only be specified when the intent is to override, IMO. If adding a new public/protected method to a base class results in its accidentally being overridden by a pre-existing conflicting derived-class method, clearly that's bad. So... 1. Specifying override on a method that doesn't override any base class method should be an error. 2. Failing to specify override on a method that does override a base class public/protected method should be an error. I thought that was what D does anyway, and for that matter that it was the whole point of the override keywordAnd adding a new private member to a base class should not break any derived classes that might happen to already use the same signature for a (private or public) method, especially since you may have no control or even knowledge of those derived classes.Given that, I'd imagine you'd be a proponent of making 'override' a required keyword? After all, not requiring it will likely lead to the same type of problem when a base-class method is removed. Yet, judging by past record, override is unlikely to ever be required.
Jan 23 2007
On Tue, 23 Jan 2007 09:20:18 -0800, kris <foo bar.com> wrote:Steve Horne wrote:1. Specifying override on a method that doesn't override any base class method should be an error. 2. Failing to specify override on a method that does override a base class public/protected method should be an error.(1) does generate an error, but (2) has never generated one, and requests to make it do so have met with silence from W for years :)Ah - ok. I'm not so sure the override modifier has much value, done this way. I guess I agree - it looks like a missed opportunity. I guess the trouble is that tightening up the rules would be big breaking change. Easy to fix, but a lot of fixing needed. Oh well. -- Remove 'wants' and 'nospam' from e-mail.
Jan 24 2007