As succinctly described here, overriding private methods in Java is invalid because a parent class's private methods are "automatically final, and hidden from the derived class". My question is largely academic.
How is it not a violation of encapsulation to not allow a parent's private method to be "overridden" (ie, implemented independently, with the same signature, in a child class)? A parent's private method cannot be accessed or inherited by a child class, in line with principles of encapsulation. It is hidden.
So, why should the child class be restricted from implementing its own method with the same name/signature? Is there a good theoretical foundation for this, or is this just a pragmatic solution of some sort? Do other languages (C++ or C#) have different rules on this?
There is no such restriction. You can do that without any problems, it's just not called "overriding".
Overridden methods are subject to dynamic dispatch, i.e. the method that is actually called is selected at runtime depending on the actual type of the object it's called on. With private method, that does not happen (and should not, as per your first statement). And that's what is meant by the statement "private methods can't be overridden".
When the method is private, it's not visible to its child. So there is no meaning of overriding it.
You can't override a private method, but you can introduce one in a derived class without a problem. This compiles fine:
Note that if you try to apply the
@Override
annotation toChild.foo()
you'll get a compile-time error. So long as you have your compiler/IDE set to give you warnings or errors if you're missing an@Override
annotation, all should be well. Admittedly I prefer the C# approach ofoverride
being a keyword, but it was obviously too late to do that in Java.As for C#'s handling of "overriding" a private method - a private method can't be virtual in the first place, but you can certainly introduce a new private method with the same name as a private method in the base class.
Well, C++ has different rules: the static or dynamic member function binding process and the access privileges enforcements are orthogonal.
Giving a member function the
private
access privilege modifier means that this function can only be called by its declaring class, not by others (not even the derived classes). When you declare aprivate
member function asvirtual
, even pure virtual (virtual void foo() = 0;
), you allow the base class to benefit from specialization while still enforcing the access privileges.When it comes to
virtual
member functions, access privileges tells you what you are supposed to do:private virtual
means that you are allowed to specialize the behavior but the invocation of the member function is made by the base class, surely in a controlled fashionprotected virtual
means that you should / must invoke the upper class version of the member function when overriding itSo, in C++, access privilege and virtualness are independent of each other. Determining whether the function is to be statically or dynamically bound is the last step in resolving a function call.
Finally, the Template Method design pattern should be preferred over
public virtual
member functions.Reference: Conversations: Virtually Yours
The article gives a practical use of a
private virtual
member function.ISO/IEC 14882-2003 §3.4.1
ISO/IEC 14882-2003 §5.2.2
I think you're misinterpreting what that post says. It's not saying that the child class is "restricted from implementing its own method with the same name/signature."
Here's the code, slightly edited:
And the quote:
The reason for that quote is that the variable
po
actually holds an instance of Derived. However, since the method is defined as private, the compiler actually looks at the type of the variable, rather than the type of the object. And it translates the method call into invokespecial (I think that's the right opcode, haven't checked JVM spec) rather than invokeinstance.I apologize for using the term override incorrectly and inconsistent with my description. My description describes the scenario. The following code extends Jon Skeet's example to portray my scenario:
Usage is like the following:
The issue I experienced is that the parent foo() method was being called even though, as the code shows, I was calling callFoo() on the child instance variable. I thought I was defining a new private method foo() in Child() which the inherited callFoo() method would call, but I think some of what kdgregory has said may apply to my scenario - possibly due to the way the derived class constructor is calling super(), or perhaps not.
There was no compiler warning in Eclipse and the code did compile. The result was unexpected.