digitalmars.D - private vs protected in Interfaces
- Andrej Mitrovic (56/56) Aug 13 2010 More code from TDPL:
- Christian Kamm (7/12) Aug 13 2010 See http://d.puremagic.com/issues/show_bug.cgi?id=4542 .
- Jonathan M Davis (6/21) Aug 13 2010 Generally speaking, if the spec and TDPL are in conflict, TDPL is suppos...
- Andrei Alexandrescu (3/23) Aug 14 2010 I think TDPL should win in this case.
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (34/35) Aug 15 2010 I am not saying that it should not be supported; but...
- Andrei Alexandrescu (37/44) Aug 15 2010 Interesting. I think Kevlin is an outstanding designer, and I agree with...
- Andrei Alexandrescu (5/24) Aug 16 2010 [snip]
- Andrej Mitrovic (3/28) Aug 14 2010 I agree, NVI really looks like a nice idiom/pattern to me, I'd hate to l...
- Andrej Mitrovic (62/65) Aug 14 2010 On page 217+218 there are two interfaces that define some final methods ...
More code from TDPL: import std.exception; interface Transmogrifier { final void thereAndBack() {} private: void transmogrify(); void untransmogrify(); } class CardboardBox : Transmogrifier { private: override void transmogrify() { } override void untramsogrify() { } } class FlippableCardboardBox : CardboardBox { private: bool flipped; override void transmogrify() { enforce(!flipped, "Can't transmogrify: box is in time machine mode"); super.transmogrify(); // should be an error, cannot invoke private // method CardboardBox.transmogrify } override void untransmogrify() { } } import std.stdio; void main() { auto obj = new FlippableCardboardBox; obj.transmogrify(); } TPDL, page 216: "Making an overridable function private in an interface..prevents an implementation from calling the super function". But the code example above compiles and runs fine. On the next page: "A simpler solution is to relax access of the two overridables in Transmogrifier from private to protected:" interface Transmogrifier { final void thereAndBack() {} protected: void transmogrify(); void untransmogrify(); } This will not work. I get back: test.d(13): Error: class test.CardboardBox interface function Transmogrifier.transmogrify isn't implemented test.d(13): Error: class test.CardboardBox interface function Transmogrifier.untransmogrify isn't implemented test.d(20): Error: class test.FlippableCardboardBox interface function Transmogrifier.transmogrify isn't implemented test.d(20): Error: class test.FlippableCardboardBox interface function Transmogrifier.untransmogrify isn't implemented test.d(20): Error: class test.FlippableCardboardBox interface function Transmogrifier.transmogrify isn't implemented test.d(20): Error: class test.FlippableCardboardBox interface function Transmogrifier.untransmogrify isn't implemented Which doesn't make any sense, the derived classes have the functions implemented. Btw Andrei, you threw that enforce in without any explanation (I don't think I saw it in any earlier examples), and you're missing an import (but I've put that in the errata).
Aug 13 2010
Andrej Mitrovic wrote:TPDL, page 216: "Making an overridable function private in an interface..prevents an implementation from calling the super function". But the code example above compiles and runs fine.See http://d.puremagic.com/issues/show_bug.cgi?id=4542 . By the D spec, private implies final. That means unimplemented private methods in interfaces have little use. Also 'private override' should be an error. Or spec and compiler should be changed to be in line with TDPL. Christian
Aug 13 2010
On Friday 13 August 2010 23:14:02 Christian Kamm wrote:Andrej Mitrovic wrote:Generally speaking, if the spec and TDPL are in conflict, TDPL is supposed to win. Still, until Walter says something about it or it's fixed, we won't know for sure. I really do think that TDPL should win out in this case though. It would not be good to be unable to do NVI. - Jonathan M DavisTPDL, page 216: "Making an overridable function private in an interface..prevents an implementation from calling the super function". But the code example above compiles and runs fine.See http://d.puremagic.com/issues/show_bug.cgi?id=4542 . By the D spec, private implies final. That means unimplemented private methods in interfaces have little use. Also 'private override' should be an error. Or spec and compiler should be changed to be in line with TDPL. Christian
Aug 13 2010
On 08/14/2010 01:20 AM, Jonathan M Davis wrote:On Friday 13 August 2010 23:14:02 Christian Kamm wrote:I think TDPL should win in this case. AndreiAndrej Mitrovic wrote:Generally speaking, if the spec and TDPL are in conflict, TDPL is supposed to win. Still, until Walter says something about it or it's fixed, we won't know for sure. I really do think that TDPL should win out in this case though. It would not be good to be unable to do NVI.TPDL, page 216: "Making an overridable function private in an interface..prevents an implementation from calling the super function". But the code example above compiles and runs fine.See http://d.puremagic.com/issues/show_bug.cgi?id=4542 . By the D spec, private implies final. That means unimplemented private methods in interfaces have little use. Also 'private override' should be an error. Or spec and compiler should be changed to be in line with TDPL. Christian
Aug 14 2010
Jonathan M Davis wrote:It would not be good to be unable to do NVI.I am not saying that it should not be supported; but... I've used NVI a number of times myself until I was convinced by Kevlin Henney that it was "a solution in search of a problem" during one of his many excellent presentations at the Silicon Valley ACCU: http://www.accu-usa.org/Slides/ACriticalViewOfCppPractices.pdf A couple of slides can't convey his thoughts, but here they are: <quote slide="27"> Non-virtual Interfaces? NVI suggests virtuals should be private and wrapped in public non-virtuals Over the last decade or so this has been proposed by some as a good practice guideline It has structural similarities with Template Method, but has a distinct form and (in)distinct motivation However, it is a solution in search of a problem On close inspection the problems it purports to resolve are better addressed by other more mature and proven techniques, e.g. the Interceptor pattern </quote> <quote slide="28"> Non-Valuable Idiom NVI lacks either a clear motivation or a clear description of benefits Motivation is often presented in terms of shotgun speculation — code simplification, instrumentation, extensibility, decoupling, thread safety, assertion checking, etc. — that does not stand up to scrutiny NVI singularly fails to adequately offer the benefits that are advertised as its motivation In practice it is a somewhat tedious and verbose technique that adds baggage to a class hierarchy </quote> Ali
Aug 15 2010
On 08/15/2010 04:01 AM, Ali Çehreli wrote:Jonathan M Davis wrote:Interesting. I think Kevlin is an outstanding designer, and I agree with him that applying NVI as a convention in languages that have little support for it is tenouos. I disagree with a few points his slides make, and am informing him of this discussion to allow him to chime in if he wants. * Slide 17: Ironically, this slides provides motivation for NVI without recognizing it. * Slide 27: "On close inspection... more mature and proven techniques, e.g. the Interceptor pattern". Maturity and proven-worthiness would suggest that most everyone should have heard of the Interceptor pattern. I knew nothing about the name so I googled for it. Google only finds 1420 hits for "interceptor pattern" compared to the 76000 hits for "non virtual interface" (both quoted to eliminate noise). I'm not saying numbers are an ultimate argument, but I find it specious that a mature and proven technique has only 1420 hits to speak for it (not to mention that the Wikipedia entry is quite underwhelming). * Slide 28: "NVI lacks either a clear motivation or a clear description of benefits" with a scathing sub-bullet. Going to the first google hit for "non virtual interface" (wikibooks.org) shows the following intent: "To modularize/refactor common before and after code fragments (e.g., invariant checking, acquiring/releasing locks) for an entire class hierarchy at one location." Not only I find it hard to frame that motivator as unclear speculation etc., but I actually find it pretty darn good. * Slide 29: The example given illustrates either an unrealistic mocking or a misunderstanding of the pattern: instead of offering _distinct_ interfaces to clients and children, it offers the same exact interface, just written twice. The one thing that sucks about NVI is the scant language support for it, issue alluded to slide 24. I would have agreed with 4 slides worth of detail on that one. In C++ a derived class is free to break NVI in quite a number of ways, notably by wrongly overriding (actually hiding) functions that aren't virtual. So in C++ NVI is clunky to enact and difficult to even maintain. I hope we fixed those in D (implementation bugs notwithstanding). AndreiIt would not be good to be unable to do NVI.I am not saying that it should not be supported; but... I've used NVI a number of times myself until I was convinced by Kevlin Henney that it was "a solution in search of a problem" during one of his many excellent presentations at the Silicon Valley ACCU: http://www.accu-usa.org/Slides/ACriticalViewOfCppPractices.pdf
Aug 15 2010
Andrei Alexandrescu wrote:On 08/15/2010 04:01 AM, Ali Çehreli wrote:[snip] Just got word from Kevlin that he's on vacation with family, so he won't reply to this anytime soon. AndreiJonathan M Davis wrote:Interesting. I think Kevlin is an outstanding designer, and I agree with him that applying NVI as a convention in languages that have little support for it is tenouos. I disagree with a few points his slides make, and am informing him of this discussion to allow him to chime in if he wants.It would not be good to be unable to do NVI.I am not saying that it should not be supported; but... I've used NVI a number of times myself until I was convinced by Kevlin Henney that it was "a solution in search of a problem" during one of his many excellent presentations at the Silicon Valley ACCU: http://www.accu-usa.org/Slides/ACriticalViewOfCppPractices.pdf
Aug 16 2010
I agree, NVI really looks like a nice idiom/pattern to me, I'd hate to loose it. On Sat, Aug 14, 2010 at 8:20 AM, Jonathan M Davis <jmdavisprog gmail.com>wrote:On Friday 13 August 2010 23:14:02 Christian Kamm wrote:Andrej Mitrovic wrote:anTPDL, page 216: "Making an overridable function private in an interface..prevents an implementation from calling the super function". But the code example above compiles and runs fine.See http://d.puremagic.com/issues/show_bug.cgi?id=4542 . By the D spec, private implies final. That means unimplemented private methods in interfaces have little use. Also 'private override' should beerror. Or spec and compiler should be changed to be in line with TDPL. ChristianGenerally speaking, if the spec and TDPL are in conflict, TDPL is supposed to win. Still, until Walter says something about it or it's fixed, we won't know for sure. I really do think that TDPL should win out in this case though. It would not be good to be unable to do NVI. - Jonathan M Davis
Aug 14 2010
On page 217+218 there are two interfaces that define some final methods with the same name, and a class that inherits from both: interface Timer { final void run() {} } interface Application { final void run() {} } class TimedApp : Timer, Application { void run() {} // cannot define run() } Okay, it hijacks both methods which are final, it won't compile which is what we want. TDPL states: "To access those methods for app of type TimedApp, you'd have to write app.Timer.run() and app.Application.run() for Timer's and Application's version", where the inheriting class does not hijack the methods. So that would look like this: interface Timer { final void run() {}; } interface Application { final void run() {}; } class TimedApp : Timer, Application { } import std.stdio; void main() { auto app = new TimedApp; app.Timer.run(); // error, no Timer property app.Application.run(); // error, no Application property } This looks to me like a DMD bug? I know I can do calls like these if a class inherits from another class: class Timer { final void run() {}; } class Application { final void run() {}; } class TimedApp : Timer//, Application { } import std.stdio; void main() { auto app = new TimedApp; app.Timer.run(); // works fine //~ app.Application.run(); } (Note I've had to comment out inheriting Application since MI is disallowed in D). This will now run. Is this a DMD bug? On Sat, Aug 14, 2010 at 4:56 PM, Andrej Mitrovic <andrej.mitrovich gmail.comwrote:I agree, NVI really looks like a nice idiom/pattern to me, I'd hate to loose it.
Aug 14 2010