www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - private method in interface

reply Michael Shulman <viritrilbia gmail.com> writes:
Hi,

The following code fails the linker, complaining about an undefined
reference to 'foo':


interface A {
  private int foo();
}

class B {
  int bar(A x) { return x.foo(); }
}

void main() { }


But if I remove the 'private' qualifier on 'foo', then it succeeds.
Shouldn't B.bar() be able to access the private A.foo(), since they
are in the same package?  If I move the definition of A into another
package, then the *compiler* fails with "interface member not
accessible", as I would expect.

Thanks!
Mike
Jun 02 2011
next sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Thu, 02 Jun 2011 13:10:14 -0400, Michael Shulman  
<viritrilbia gmail.com> wrote:

 Hi,

 The following code fails the linker, complaining about an undefined
 reference to 'foo':


 interface A {
   private int foo();
 }

 class B {
   int bar(A x) { return x.foo(); }
 }

 void main() { }


 But if I remove the 'private' qualifier on 'foo', then it succeeds.
 Shouldn't B.bar() be able to access the private A.foo(), since they
 are in the same package?  If I move the definition of A into another
 package, then the *compiler* fails with "interface member not
 accessible", as I would expect.

Private methods are non-virtual, so I'm pretty sure they are not supposed to be allowed in an interface. But I suppose private could also mean private final, in which case you have to provide an implementation for foo in the interface. This would be in line with the error message. -Steve
Jun 02 2011
parent Kagamin <spam here.lot> writes:
Jonathan M Davis Wrote:

 http://d.puremagic.com/issues/show_bug.cgi?id=4542
 http://d.puremagic.com/issues/show_bug.cgi?id=2051

Nothing prevents compiler from considering class private methods as final and allow implement interface private methods (possibly with requirement for `override` keyword).
Jun 02 2011
prev sibling next sibling parent Michael Shulman <viritrilbia gmail.com> writes:
On Thu, Jun 2, 2011 at 10:31 AM, Steven Schveighoffer
<schveiguy yahoo.com> wrote:
 Private methods are non-virtual, so I'm pretty sure they are not supposed to
 be allowed in an interface.

 But I suppose private could also mean private final, in which case you have
 to provide an implementation for foo in the interface.

In section 6.9.1 of "The D Programming Language" about Non-Virtual Interfaces, there is an example (p214) of an interface which defines two private methods without implementation. But now that you point it out, that code also fails the linker for me. Is that book out of sync with the implementation?
 This would be in line with the error message.

It is true that if I replace "private" with "final" I get the same error message. That is also puzzling to me; I would expect a final method in an interface without an implementation to be a *compiler* error, since there is no way anyone else can implement it. Is there? Mike
Jun 02 2011
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Thu, 02 Jun 2011 15:01:31 -0400, Michael Shulman  
<viritrilbia gmail.com> wrote:

 On Thu, Jun 2, 2011 at 10:31 AM, Steven Schveighoffer
 <schveiguy yahoo.com> wrote:
 Private methods are non-virtual, so I'm pretty sure they are not  
 supposed to
 be allowed in an interface.

 But I suppose private could also mean private final, in which case you  
 have
 to provide an implementation for foo in the interface.

In section 6.9.1 of "The D Programming Language" about Non-Virtual Interfaces, there is an example (p214) of an interface which defines two private methods without implementation. But now that you point it out, that code also fails the linker for me. Is that book out of sync with the implementation?

I'm not sure, I don't have a copy of the book, so I'm not sure of the context. I remember reading posts claiming that the book intends for private methods to be virtual, but I can't be sure. All I know is, the official position of D is that the book overrules the current spec/implementation. So if it seems the book is not agreeing with the current spec, it's likely a bug in the spec/compiler. If you believe this to be the case, please file a bug on bugzilla http://d.puremagic.com/issues/enter_bug.cgi Put [TDPL] at the beginning of the summary.
 This would be in line with the error message.

It is true that if I replace "private" with "final" I get the same error message. That is also puzzling to me; I would expect a final method in an interface without an implementation to be a *compiler* error, since there is no way anyone else can implement it. Is there?

In D, you do not need to provide an implementation when declaring a function. For example, if you want to hide the details of a function, you can just declare it in a public file, but actually build your library with a private file that contains the implementation. This way, the end-user cannot see the source. .di files are supposed to be for this, but I think in practice, .di and .d files are treated the same by the compiler. You can see a great example of this in object.di included with the compiler (src/druntime/import/object.di). -Steve
Jun 02 2011
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On 2011-06-02 12:01, Michael Shulman wrote:
 On Thu, Jun 2, 2011 at 10:31 AM, Steven Schveighoffer
 
 <schveiguy yahoo.com> wrote:
 Private methods are non-virtual, so I'm pretty sure they are not supposed
 to be allowed in an interface.
 
 But I suppose private could also mean private final, in which case you
 have to provide an implementation for foo in the interface.

In section 6.9.1 of "The D Programming Language" about Non-Virtual Interfaces, there is an example (p214) of an interface which defines two private methods without implementation. But now that you point it out, that code also fails the linker for me. Is that book out of sync with the implementation?
 This would be in line with the error message.

It is true that if I replace "private" with "final" I get the same error message. That is also puzzling to me; I would expect a final method in an interface without an implementation to be a *compiler* error, since there is no way anyone else can implement it. Is there?

http://d.puremagic.com/issues/show_bug.cgi?id=4542 http://d.puremagic.com/issues/show_bug.cgi?id=2051 - Jonathan M Davis
Jun 02 2011
prev sibling next sibling parent Michael Shulman <viritrilbia gmail.com> writes:
On Thu, Jun 2, 2011 at 12:20 PM, Jonathan M Davis <jmdavisProg gmx.com> wrote:
 http://d.puremagic.com/issues/show_bug.cgi?id=4542
 http://d.puremagic.com/issues/show_bug.cgi?id=2051

Thank you! I think this answers my question completely; I just need to change "private" to "protected". Is there a place on the web recording "errata" of this sort for TDPL? Here is a related question which puzzles me, from reading http://d-programming-language.org/function.html#virtual-functions What is the difference between "private" and "final private"? Mike
Jun 02 2011
prev sibling next sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On 2011-06-02 12:59, Michael Shulman wrote:
 On Thu, Jun 2, 2011 at 12:20 PM, Jonathan M Davis <jmdavisProg gmx.com> 

 http://d.puremagic.com/issues/show_bug.cgi?id=4542
 http://d.puremagic.com/issues/show_bug.cgi?id=2051

Thank you! I think this answers my question completely; I just need to change "private" to "protected". Is there a place on the web recording "errata" of this sort for TDPL?

http://erdani.com/tdpl/errata/index.php?title=Main_Page
 Here is a related question which puzzles me, from reading
 http://d-programming-language.org/function.html#virtual-functions
 What is the difference between "private" and "final private"?

At present, there is no difference between a member function which is private and one which is final private. All private functions are non-virtual and are not overridable. So, final does nothing. If/When dmd is updated to match TDPL and make private functions virtual and overridable, then private functions _will_ be virtual and overridable, and final will be required in order to make them non-overridable again (and assuming that the private function in question does not override a private funtion from a base class, the compiler should be able to optimize it so that it's non-virtual just like private currently is). But for now, putting final on a private function does nothing. - Jonathan M Davis
Jun 02 2011
prev sibling next sibling parent Michael Shulman <viritrilbia gmail.com> writes:
Thanks!

On Thu, Jun 2, 2011 at 2:36 PM, Jonathan M Davis <jmdavisProg gmx.com> wrote:
 On 2011-06-02 12:59, Michael Shulman wrote:
 On Thu, Jun 2, 2011 at 12:20 PM, Jonathan M Davis <jmdavisProg gmx.com>

 http://d.puremagic.com/issues/show_bug.cgi?id=4542
 http://d.puremagic.com/issues/show_bug.cgi?id=2051

Thank you! I think this answers my question completely; I just need to change "private" to "protected". Is there a place on the web recording "errata" of this sort for TDPL?

http://erdani.com/tdpl/errata/index.php?title=Main_Page
 Here is a related question which puzzles me, from reading
 http://d-programming-language.org/function.html#virtual-functions
 What is the difference between "private" and "final private"?

At present, there is no difference between a member function which is private and one which is final private. All private functions are non-virtual and are not overridable. So, final does nothing. If/When dmd is updated to match TDPL and make private functions virtual and overridable, then private functions _will_ be virtual and overridable, and final will be required in order to make them non-overridable again (and assuming that the private function in question does not override a private funtion from a base class, the compiler should be able to optimize it so that it's non-virtual just like private currently is). But for now, putting final on a private function does nothing. - Jonathan M Davis

Jun 02 2011
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On 2011-06-02 23:53, Kagamin wrote:
 Jonathan M Davis Wrote:
 http://d.puremagic.com/issues/show_bug.cgi?id=4542
 http://d.puremagic.com/issues/show_bug.cgi?id=2051

Nothing prevents compiler from considering class private methods as final and allow implement interface private methods (possibly with requirement for `override` keyword).

It would be possible but inconsistent. It would also likely be more complicated to implement than simply making private functions virtual and overridable. I don't really like the idea of private functions being virtual by default though, so maybe your suggestion would be a good one. - Jonathan M Davis
Jun 02 2011
prev sibling next sibling parent Michael Shulman <viritrilbia gmail.com> writes:
On Thu, Jun 2, 2011 at 11:55 PM, Jonathan M Davis <jmdavisProg gmx.com> wrote:
 I don't really like the idea of private functions being virtual
 by default though, so maybe your suggestion would be a good one.

Speaking as a newbie with very little D experience, the idea of private functions being non-virtual would make perfect sense to me if 'private' meant restricted to a single class, as it does in C++. The situation of a derived class being able to override a private function from an interface or base class, but not *call* the overridden function, seems a bit weird and pointless; using 'protected' does make more sense to me for that use case. However, given that in D, 'private' only means restricted to a *module*, it's less clear to me why private functions should be singled out as non-virtual. I might want certain methods to be accessible only within a given module, but still allow them to be overridden within a class hierarchy that exists entirely inside that module. Unless the point of view is that each class should always exist in its own module? Mike
Jun 03 2011
prev sibling next sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On 2011-06-03 11:13, Michael Shulman wrote:
 On Thu, Jun 2, 2011 at 11:55 PM, Jonathan M Davis <jmdavisProg gmx.com> 

 I don't really like the idea of private functions being virtual
 by default though, so maybe your suggestion would be a good one.

Speaking as a newbie with very little D experience, the idea of private functions being non-virtual would make perfect sense to me if 'private' meant restricted to a single class, as it does in C++. The situation of a derived class being able to override a private function from an interface or base class, but not *call* the overridden function, seems a bit weird and pointless; using 'protected' does make more sense to me for that use case.

Actually, C++ has exactly this behavior. You can overload private functions in C++. That's where the whole Non-Virtual Interface paradigm came from, I believe. However, in C++, functions are only virtual if you make them virtual (which you don't normally do with private functions unless you're doing NVI), unlike D.
 However, given that in D, 'private' only means restricted to a
 *module*, it's less clear to me why private functions should be
 singled out as non-virtual. I might want certain methods to be
 accessible only within a given module, but still allow them to be
 overridden within a class hierarchy that exists entirely inside that
 module. Unless the point of view is that each class should always
 exist in its own module?

No, there would be nothing wrong with overriding private member functions within a module with derived classes (assuming that private were overridable). That would be a bit weird, generally-speaking, but it would be perfectly legitimate. There are no restrictions on how many classes or structs you put in a module, and the core D community does not seem to think that code should necessarily be divided that way. For instance, both std.container and std.datetime in Phobos have multiple types defined within them. So, you could define as many classes or structs in a module as you want to. The main issue would be if the module got too large (which some have accussed std.datetime of doing). - Jonathan M Davis
Jun 03 2011
prev sibling next sibling parent Michael Shulman <viritrilbia gmail.com> writes:
On Fri, Jun 3, 2011 at 11:22 AM, Jonathan M Davis <jmdavisProg gmx.com> wrote:
 However, given that in D, 'private' only means restricted to a
 *module*, it's less clear to me why private functions should be
 singled out as non-virtual. I might want certain methods to be
 accessible only within a given module, but still allow them to be
 overridden within a class hierarchy that exists entirely inside that
 module. Unless the point of view is that each class should always
 exist in its own module?

No, there would be nothing wrong with overriding private member functions within a module with derived classes (assuming that private were overridable).

Okay. Then I don't quite understand the rationale for all private functions being non-virtual. Mike
Jun 03 2011
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On 2011-06-03 11:59, Michael Shulman wrote:
 On Fri, Jun 3, 2011 at 11:22 AM, Jonathan M Davis <jmdavisProg gmx.com> 

 However, given that in D, 'private' only means restricted to a
 *module*, it's less clear to me why private functions should be
 singled out as non-virtual. I might want certain methods to be
 accessible only within a given module, but still allow them to be
 overridden within a class hierarchy that exists entirely inside that
 module. Unless the point of view is that each class should always
 exist in its own module?

No, there would be nothing wrong with overriding private member functions within a module with derived classes (assuming that private were overridable).

Okay. Then I don't quite understand the rationale for all private functions being non-virtual.

Efficiency. Virtual calls cost more than non-virtual calls. And if you're never going to override a function, why have it be virtual and incur that extra cost? C++ defaults to non-virtual and has the virtual modifier for making functions virtual, which gives you the efficiency by default with the flexibility to make them virtual if you want to. The problem is that it's still possible to override non-virtual functions, which is almost always a bug. Java took the route of making all functions virtual except where the compiler optimizes them to be non-virtual. D did the same except for private functions, likely on the theory that you basically never override private functions, so why incur the cost? And if you don't know about NVI, having a virtual private function is just plain weird. Lots of people are surprised to find out that it's legal to override private functions like that in C++. So, in most cases, you don't want virtual private functions. The overridability is generally useless and it costs more to call them. Worse, they can't be inlined, because the call is polymorphic and you don't know whether the version of the function in the current class or one in a derived class will be called. The one exception as far as usefulness goes is the NVI idiom, and TDPL said that you could do it (I think because Andrei didn't realize that you couldn't rather than because it was intended to be changed in the language). However, you can still effectively do NVI with protected functions, so arguably, the costs to making private functions virtual far outweigh the benefits. But the fact that TDPL says that private is overridable for NVI may make it so that the language is changed to allow it. We'll have to see. In any case, the reason that you don't normally want private functions to be virtual is because virtual functions cannot generally be inlined and are less efficient than non-virtual functions. - Jonathan M Davis
Jun 03 2011
prev sibling next sibling parent reply Michael Shulman <viritrilbia gmail.com> writes:
On Fri, Jun 3, 2011 at 1:02 PM, Jonathan M Davis <jmdavisProg gmx.com> wrote:
 And if you don't know about NVI, having a
 virtual private function is just plain weird.

Well, it makes perfect sense to me, once given that in D, 'private' allows access from anywhere in the same module, rather than only in the defining class. I agree that it's weird and surprising in C++. Are 'package' qualified functions also non-virtual? The documentation http://d-programming-language.org/function.html#virtual-functions says that "all non-static non-private non-template member functions are virtual", but I get the same sort of linker errors with 'package' functions that I do with 'private' ones, even with code that's all in one module. Mike
Jun 03 2011
parent Jacob Carlborg <doob me.com> writes:
On 2011-06-03 23:55, Michael Shulman wrote:
 On Fri, Jun 3, 2011 at 1:02 PM, Jonathan M Davis<jmdavisProg gmx.com>  wrote:
 And if you don't know about NVI, having a
 virtual private function is just plain weird.

Well, it makes perfect sense to me, once given that in D, 'private' allows access from anywhere in the same module, rather than only in the defining class. I agree that it's weird and surprising in C++. Are 'package' qualified functions also non-virtual? The documentation http://d-programming-language.org/function.html#virtual-functions says that "all non-static non-private non-template member functions are virtual", but I get the same sort of linker errors with 'package' functions that I do with 'private' ones, even with code that's all in one module. Mike

The current implementation of "package" is non-virtual and, as far as I know, has always been like that. What it's actually supposed to be, I don't know. -- /Jacob Carlborg
Jun 04 2011
prev sibling next sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On 2011-06-03 14:55, Michael Shulman wrote:
 On Fri, Jun 3, 2011 at 1:02 PM, Jonathan M Davis <jmdavisProg gmx.com> 

 And if you don't know about NVI, having a
 virtual private function is just plain weird.

Well, it makes perfect sense to me, once given that in D, 'private' allows access from anywhere in the same module, rather than only in the defining class. I agree that it's weird and surprising in C++. Are 'package' qualified functions also non-virtual? The documentation http://d-programming-language.org/function.html#virtual-functions says that "all non-static non-private non-template member functions are virtual", but I get the same sort of linker errors with 'package' functions that I do with 'private' ones, even with code that's all in one module.

I would expect package to be virtual, but Walter could have implemented it as non-virtual on the theory that if you wanted it to be overridden, it would be protected (which would be the normal thing to do when you intend to have a derived class override a member function). I'd suggest opening a bug report. It wouldn't hurt my feelings any if private and package were both always non- virtual, but TDPL says that they're both virtual, and the online docs says that package is virtual, so either the compiler needs to be fixed or TDPL and the docs need to be changed. Regardless, I would have hoped that you'd get an error at compile time about overriding a non-virtual function if package is non-virtual, so at minimum, the error message needs to be improved. So, open a bug report on it, and Walter can make whatever changes are appropriate. - Jonathan M Davis
Jun 03 2011
prev sibling next sibling parent Michael Shulman <viritrilbia gmail.com> writes:
On Fri, Jun 3, 2011 at 3:07 PM, Jonathan M Davis <jmdavisProg gmx.com> wrote:
 I'd suggest opening a bug report.

Okay, will do.
 Regardless, I would have hoped that you'd get an error at compile
 time about overriding a non-virtual function if package is
 non-virtual

It appears that overriding a non-virtual, non-abstract method (private or package) just hides the base-class version when the reference is of derived type, exactly as happens in C++ for non-virtual methods. E.g. class A { private void dostuff() { writeln ("In A.dostuff"); } } class B : A { private void dostuff() { writeln ("In B.dostuff"); } } void main () { B y = new B(); A x = y; y.dostuff(); x.dostuff(); } prints In B.dostuff In A.dostuff I would have kind of hoped for a compiler error too, given that C++ programmers generally seem to feel that overriding non-virtual methods in this way is a bad idea. Mike
Jun 03 2011
prev sibling next sibling parent Michael Shulman <viritrilbia gmail.com> writes:
The bug report appears to already exist:
http://d.puremagic.com/issues/show_bug.cgi?id=3258

On Fri, Jun 3, 2011 at 3:07 PM, Jonathan M Davis <jmdavisProg gmx.com> wrote:
 On 2011-06-03 14:55, Michael Shulman wrote:
 On Fri, Jun 3, 2011 at 1:02 PM, Jonathan M Davis <jmdavisProg gmx.com>

 And if you don't know about NVI, having a
 virtual private function is just plain weird.

Well, it makes perfect sense to me, once given that in D, 'private' allows access from anywhere in the same module, rather than only in the defining class. I agree that it's weird and surprising in C++. Are 'package' qualified functions also non-virtual? The documentation http://d-programming-language.org/function.html#virtual-functions says that "all non-static non-private non-template member functions are virtual", but I get the same sort of linker errors with 'package' functions that I do with 'private' ones, even with code that's all in one module.

I would expect package to be virtual, but Walter could have implemented it as non-virtual on the theory that if you wanted it to be overridden, it would be protected (which would be the normal thing to do when you intend to have a derived class override a member function). I'd suggest opening a bug report. It wouldn't hurt my feelings any if private and package were both always non- virtual, but TDPL says that they're both virtual, and the online docs says that package is virtual, so either the compiler needs to be fixed or TDPL and the docs need to be changed. Regardless, I would have hoped that you'd get an error at compile time about overriding a non-virtual function if package is non-virtual, so at minimum, the error message needs to be improved. So, open a bug report on it, and Walter can make whatever changes are appropriate. - Jonathan M Davis

Jun 03 2011
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On 2011-06-03 19:44, Michael Shulman wrote:
 On Fri, Jun 3, 2011 at 3:07 PM, Jonathan M Davis <jmdavisProg gmx.com> 

 I'd suggest opening a bug report.

Okay, will do.
 Regardless, I would have hoped that you'd get an error at compile
 time about overriding a non-virtual function if package is
 non-virtual

It appears that overriding a non-virtual, non-abstract method (private or package) just hides the base-class version when the reference is of derived type, exactly as happens in C++ for non-virtual methods. E.g. class A { private void dostuff() { writeln ("In A.dostuff"); } } class B : A { private void dostuff() { writeln ("In B.dostuff"); } } void main () { B y = new B(); A x = y; y.dostuff(); x.dostuff(); } prints In B.dostuff In A.dostuff I would have kind of hoped for a compiler error too, given that C++ programmers generally seem to feel that overriding non-virtual methods in this way is a bad idea.

Try to compile with -w. My guess is that you will get a compiler error. But yes, it really should give an error regardless. - Jonathan M Davis
Jun 03 2011
prev sibling next sibling parent Michael Shulman <viritrilbia gmail.com> writes:
On Fri, Jun 3, 2011 at 8:54 PM, Jonathan M Davis <jmdavisProg gmx.com> wrote:
 Try to compile with -w. My guess is that you will get a compiler error.

Nope.
Jun 03 2011
prev sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On 2011-06-03 21:52, Michael Shulman wrote:
 On Fri, Jun 3, 2011 at 8:54 PM, Jonathan M Davis <jmdavisProg gmx.com> 

 Try to compile with -w. My guess is that you will get a compiler error.

Nope.

Then file a bug report on it. As I understand it, overriding a non-virtual function in D should be illegal. Certainly, it goes against how D deals with virtuality in general. - Jonathan M Davis
Jun 03 2011