Take the following code:
public class Parent
{
public String doIt(Object o) {
return "parent";
}
}
public class Child extends Parent
{
public String doIt(Object s) {
return super.doIt(s) + ": " + "child";
}
}
public class Poly
{
public String makeItHappen() {
Parent p = new Child();
return p.doIt("test");
}
}
Due to the fact that Child.doIt() overrides Parent.doIt(), invoking Poly.makeItHappen() results in this being printed to the console:
parent: child
However, if I make a change in Child.doIt() to look like this:
public String doIt(String s) {
return super.doIt(s) + ": " + "child";
}
Now Child.doIt() does not override Parent.doIt(). When you invoke Poly.makeItHappen(), you get this result:
parent
I'm a bit puzzled by this. The compile-time type of p is Parent so I certainly understand it finding Parent.doIt() as a potentially applicable method, but, given that the run-time type of p is Child, I'm not certain why Child.doIt() is not. Presuming that they are both identified as potentially applicable methods, I would expect Child.doIt(String) to be invoked over Parent.doIt(Object) as it is more specific.
I've tried consulting the JLS and found this bit:
15.12.1 Compile-Time Step 1: Determine Class or Interface to Search
...
In all other cases, the qualified name has the form FieldName . Identifier; then the name of the method is the Identifier and the class or interface to search is the declared type T of the field named by the FieldName, if T is a class or interface type, or the upper bound of T if T is a type variable.
To me, that says that the compile-time type of p would be used. This makes some sense when I see Parent.doIt(Object) being invoked while Child.doIt(String) is not. But it doesn't make sense in the terms of the polymorphic behavior noted when Child.doIt() properly overrides Parent.doIt() - in that case, both methods of Parent and Child are being analyzed to find potentially applicable methods so why not in the second case, as well?
I know I'm missing something here, but I just can't figure out why I'm seeing the behavior that I am. If anyone could shed some insight into this, I'd appreciate it.
EDIT: FOUND THE ANSWER:
Thanks to Jack's response, I was able to find the answer within the JLS. The section of the JLS I referred to earlier was actually focused on finding the correct method at compile time and did not cover the process of invoking the correct method at run time. That portion of the process can be found the section of the JLS titled 15.12.4 Runtime Evaluation of Method Invocation.
In there, I found this bit of text:
Otherwise, the invocation mode is interface, virtual, or super, and overriding may occur. A dynamic method lookup is used. The dynamic lookup process starts from a class S, determined as follows:
My invocation mode is virtual, so the above statement applies...
If the invocation mode is interface or virtual, then S is initially the actual run-time class R of the target object.
...
The dynamic method lookup uses the following procedure to search class S, and then the superclasses of class S, as necessary, for method m.
Okay, so this seemed very odd to me. According to this, the JVM is going to start looking for an applicable method in Child to invoke, which would lead me to believe that Child.doIt(String) would be invoked. But, reading on...
Let X be the compile-time type of the target reference of the method invocation.
...
If class S contains a declaration for a non-abstract method named m with the same descriptor (same number of parameters, the same parameter types, and the same return type) required by the method invocation as determined at compile time (§15.12.3), then:
The class "S", which would be Child, does indeed contain a method with the same descriptor as the method invocation determined at compile time (String "is a" Object, after all, so the descriptors are identical). It still seems to be like Child.doIt(String) should be getting invoked, but reading on...
If the invocation mode is virtual, and the declaration in S overrides (§8.4.8.1) X.m, then the method declared in S is the method to be invoked, and the procedure terminates.
...
Otherwise, if S has a superclass, this same lookup procedure is performed recursively using the direct superclass of S in place of S; the method to be invoked is the result of the recursive invocation of this lookup procedure.
The bit in bold is the really important part of this. As I mentioned, when I changed the method Child.doIt(), it no longer was overriding the doIt() method from Parent. So, even though the JVM is evaluating the Child.doIt() method as a potential candidate for invocation, it fails to be invoked because it does not override the method defined in X, which is Parent. I was really getting hung up because I thought the JVM was not even check Child.doIt as a potentially applicable method, and that didn't seem correct. Now I believe that the JVM is checking that method as a potentially applicable method, but then disregards it because it doesn't properly override the parent method. It's a situation in which I thought that the method from the subclass would be invoked, not because it overrides the parent class method, but because it is the most specific. In this case, however, that isn't true.
The next line in the JLS simply explains that this procedure executes recursively over superclasses, leading Parent.doIt(Object) to be invoked.
Intuitively, this made complete sense to me but I just couldn't wrap my head around how the JVM was actually executing this process. Of course, looking in the correct part of the JLS would have helped a great deal.
Dynamic binding of the method applies at runtime between different implementations with the same signature but the set of all possible methods is determined statically when the compilers look at the signature. Since you declare p as a Parent class, at runtime it will look for a method that is present in the Parent class and, if a more specific implementation is present (because of a subclass, like in your example), then it will be chosen instead that the ancestor one.
Since your method does not override anything, at compile time it will choose a different signature (the one with Object) and ignore it. It doesn't appear as a matching possibility at runtime because of the type of attribute p.
Your answer is actually pretty simple: your change to the method broke your use of inheritance.
The Parent only has one doIt method, and it take an Object parameter. When you call doIt("test") on the parent, it looks to see if it is overridden in the child. Since doIt(Object s) is not overridden in the child, the parent method is utilized. Even though, you pass a String, the parent method will still be called since doIt(Object s) is not the same as doIt(String s).
Simply put, you are not overriding the method when you change the signature, you are overloading it.
The method signature to be invoked is determined at compile time, so p.doIt("test") will invoke the doIt(Object o) method of the appropriate class at runtime. doIt(String s) isn't even looked at. Imagine that Child.java didn't exist at the time that the Poly makeItHappen was written--you would also have to abstract the Child constructor away into a factory method in a different class to get it to compile. You could re-implement the factory method and Child.java without ever recompiling Poly.java. This allows you to program to the interface provided by the base class and relatively efficient function invocation. Your Poly makeItHappen only needs to know that a doIt(Object o) exists.
If you think of the possible implementation of inheritance as through a virtual function table, then doIt(String s) and doIt(Object o) have different table entries. Parent only has an entry for doIt(Object o). Child has both an entry for doIt(Object o) that is the same body as Parent and an entry for doIt(String s) that is its own. At compile time, the method to be invoked is the one in the doIt(Object o) slot.
You upcasted the Child to Parent
Parent p = new Child();
When you invoke p.doIt("test"); the only way you're going to get Child behavior is via an overridden method.
Since you changed the method in Child to doIt(String s), it is no longer overriding anything in Parent and so doIt(Object o) is called in the Parent.
Hmm, trying to address the 'why' the runtime doesn't play hide and go seek with the entire class definition looking for 'better' matches to a method than the one the compiler asked for, will go for an example. Obviously this API is horrible in the first place, but you can imagine how the situation could happen accidentally with very long method signatures.
/**
* Vendor API you program to
*/
public class IPv4Manager {
public void terminateSocket(Object obj) {
//terminate IPv4 socket
}
}
/**
* Vendor class that's injected at runtime that you have no knowledge of
* and do not compile against.
*/
public class IPv4And6Manager extends IPv4Manager {
public void terminateSocket(Byte[] packet) {
//terminate IPv6 socket
}
}
/**
*Your user code
*/
public void terminateIPv4Socket(Byte[] packet) {
IPv4Manager manager = managerFactory.getV4Manager(); //returns you an instance of 4And6Manager
manager.terminateSocket(packet);
}
Do you really want the runtime to try to outsmart you and call a "better" method than the one the compiler asked for?
Related
This question already has answers here:
Why is it that we cannot override static and final methods? [duplicate]
(5 answers)
Closed 1 year ago.
In Java, what is the actual reason behind the inability to write a method in a sub class which has the same name as a final method in the super class? (Please note that I am not trying to override the method, this is why I have put the keyword final.)
Please see the example below:
class A {
public final void method() {
System.out.println("in method A");
}
}
class B extends A {
public void method() {
System.out.println("in method B");
}
}
The problem is expressed as "'method()' cannot override 'method()' in 'A'; overridden method is final" in the IDE; however, I would like to understand what it is about this situation that leads the compiler to fail.
Because in java, overriding isn't optional.
Names of methods at the class level.
At the class level (as in, what is in a class file, and what a JVM executes), method names include their return type and their parameter types (and, of course, the name). At the JVM level, varargs doesn't exist (it's an array instead), generics do not exist (they are erased for the purposes of signature), and the throws clause isn't a part of the story. But other than that, this method:
public void foo(String foo, int bar, boolean[] baz, long... args) throws Exception {}
turns into this name at the class file level:
foo(Ljava/lang/String;I[Z[J)V
which seems like gobbledygook, but [ is 'array of', the primitives get one letter each (Z for boolean, J for longs, I for integer), V is for void, and L is for: Object type. Now it makes sense.
That really is the method name at the class level, effectively (well, we call this its signature). ANY invocation of a method in java, at the class level, always uses the complete signature. This means javac simply cannot compile a method call unless it actually knows the exact method you're invoking, which is why javac doesn't work unless you have the full classpath of everything you're calling available as you compile.
Overriding isn't optional!
At the class level, if you define a method whose full signature matches, exactly, a signature in your parent class, then it is overriding that method. Period. You can't not. #Override as an annotation doesn't affect this in the slightest (That annotation merely causes the compiler to complain if you aren't overriding anything, it's compiler-checked documentation, that's all it is).
javac goes even further
As a language thing, javac will make bridges if you want to tighten the return type. Given:
class Parent {
Object foo() { return null; }
}
class Child extends Parent {
String foo() { return null; }
}
Then at the class level, the full signature of the one method in Parent is foo()Ljava/lang/Object; whereas the one in Child has foo()Ljava/lang/String; and thus these aren't the same method and Child's foo would appear not to be overriding Parent's foo.
But javac intervenes, and DOES make these override. It does this by actually making 2 methods in Child. You can see this in action! Write the above, compile it, and run javap -c -v on Child and you see these. javac makes 2 methods: Both foo()Ljava/lang/String; and foo()Ljava/lang/Object; (which does have the same signature and thus overrides, by definition, Parent's implementation). That second one is implemented as just calling the 'real' foo (the one returning string), and gets the synthetic flag.
Final is what it is
Which finally gets to your problem: Given that final says: I cannot be overridden, then, that's it. You've made 2 mutually exclusive rules now:
Parent's foo cannot be overriden
Child's foo, by definition (because its signatures match), overrides Parent's foo
Javac will just end it there, toss an error in your face, and call it a day. If you imagined some hypothetical javac update where this combination of factors ought to result in javac making a separate method: But, how? At the class level, same signature == same method (it's an override), so what do you propose? That java add a 0 to the end of the name?
If that's the plan, how should javac deal with this:
Parent p = new Child();
p.foo();
Which foo is intended there? foo()Ljava/lang/Object; from Parent, or foo0()L/java/Object; from child?
You can write a spec that gives an answer to this question (presumably, here it's obvious: Parent's foo; had you written Child c = new Child(); c.foo(); then foo0 was intended, but that makes the language quite complicated, and for what purpose?
The java language designers did not think this is a useful exercise and therefore didn't add this complication to the language. I'm pretty sure that was clearly the right call, but your opinion may of course be different.
Final means not just that you can’t override it, it means you can’t work around having that method get called.
When you subclass the object, if you could make a method that shadows that final method, then you could prevent the superclass method from functioning, or substitute some other functionality than what the user of the object would expect. This would allow introducing malicious code and would defeat the purpose of making methods final.
In your case it sounds like making the superclass method final may not have been the best choice.
Consider the multilevel inheritance hierarchy in Java:
public class First {public String name() { return "First"; }}
public class Second extends First {
public void m1() {
System.out.print(super.name() + " rules");
System.out.prinln(" but " + name() + " is even better.");
}
public String name() { return "Second"; }}
public class Third extends Second {public String name() { return "Third"; }}
The Third class doesn't override the m1 method- it just inherits it. So if you run the following code:
Third varThird = new Third();
varThird.m1();
You get:
First rules but Third is even better.
This seems to violate the rule that at runtime, the actual type of the object is used to determine which implementation of the method is run. The method from the Second class appears to be the method that is run. How do you reconcile rules from Java inheritance (public methods are inherited by subclasses) with rules from polymorphism (at runtime, Java uses an object's actual type to determine which version of the method is implemented). Do methods that are not overridden in the subclass actually get "inherited"?
Ok, I think I undenstand the question now. You are confused about why super is rot resolved at runtime.
The reason is simple. Java only use the exact type to determine which method to call, for virtual methods. But constructors are not virtual, so a call to a constructor is always determined at compile time.
The search starts at the subtype for the method. Then the JVM successively goes further up the inheritance hierarchy to find the specific method.
It is called dynamic binding if I remember correctly.
Edit
Okay you are wondering why you get Third is even better. when m1() is only defined in Second. You are expecting the output Second is even better.
The method is inherited vom Subtyp Second as the JVM uses this method in the inheritance hierarchy as Third does not override this method.
In second you refer to
super().name where super() refers to the parent which in this case is First and therefore you get First rules but
Then you are invoking name() method which is defined in Third and therefore returning the name defined in Third
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?
You can't override a private method, but you can introduce one in a derived class without a problem. This compiles fine:
class Base
{
private void foo()
{
}
}
class Child extends Base
{
private void foo()
{
}
}
Note that if you try to apply the #Override annotation to Child.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 of override 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, allowing private methods to be overwritten will either cause a leak of encapsulation or a security risk. If we assume that it were possible, then we’d get the following situation:
Let's say that there's a private method boolean hasCredentials() then an extended class could simply override it like this:
boolean hasCredentials() { return true; }
thus breaking the security check.
The only way for the original class to prevent this would be to declare its method final. But now, this is leaks implementation information through the encapsulation, because a derived class now cannot create a method hasCredentials any more – it would clash with the one defined in the base class.
That’s bad: lets say this method doesn’t exist at first in Base. Now, an implementor can legitimately derive a class Derived and give it a method hasCredentials which works as expected.
But now, a new version of the original Base class is released. Its public interface doesn’t change (and neither do its invariants) so we must expect that it doesn’t break existing code. Only it does, because now there’s a name clash with a method in a derived class.
I think the question stems from a misunderstanding:
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)
The text inside the parentheses is the opposite of the text before it. Java does allow you to “independently implement [a private method], with the same signature, in a child class”. Not allowing this would violate encapsulation, as I’ve explained above.
But “to not allow a parent's private method to be "overridden"” is something different, and necessary to ensure encapsulation.
"Do other languages (C++ or C#) have different rules on this?"
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 a private member function as virtual, 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 fashion
protected virtual means that you should / must invoke the upper class version of the member function when overriding it
So, 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
Name lookup may associate more than one declaration with a name if it finds the name to be a function name; the declarations are said to form a set of overloaded functions (13.1). Overload resolution (13.3) takes place after name lookup has succeeded. The access rules (clause 11) are considered only once name lookup and function overload resolution (if applicable) have succeeded. Only after name lookup, function overload resolution (if applicable) and access checking have succeeded are the attributes introduced by the name’s declaration used further in expression processing (clause 5).
ISO/IEC 14882-2003 §5.2.2
The function called in a member function call is normally selected according to the static type of the object expression (clause 10), but if that function isvirtualand is not specified using aqualified-idthen the function actually called will be the final overrider (10.3) of the selected function in the dynamic type of the object expression [Note: the dynamic type is the type of the object pointed or referred to by the current value of the object expression.
A parent's private method cannot be accessed or inherited by a child class, inline 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?
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".
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:
public class PrivateOverride {
private static Test monitor = new Test();
private void f() {
System.out.println("private f()");
}
public static void main(String[] args) {
PrivateOverride po = new Derived();
po.f();
});
}
}
class Derived extends PrivateOverride {
public void f() {
System.out.println("public f()");
}
}
And the quote:
You might reasonably expect the output to be “public f( )”,
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.
It seems to be a matter of choice and definition. The reason you can't do this in java is because the specification says so, but the question were more why the specification says so.
The fact that C++ allows this (even if we use virtual keyword to force dynamic dispatch) shows that there is no inherent reason why you couldn't allow this.
However it seem to be perfectly legal to replace the method:
class B {
private int foo()
{
return 42;
}
public int bar()
{
return foo();
}
}
class D extends B {
private int foo()
{
return 43;
}
public int frob()
{
return foo();
}
}
Seems to compile OK (on my compiler), but the D.foo is not related to B.foo (ie it doesn't override it) - bar() always return 42 (by calling B.foo) and frob() always returns 43 (by calling D.foo) no matter whether called on a B or D instance.
One reason that Java does not allow override the method would be that they didn't like to allow the method to be changed as in Konrad Rudolph's example. Note that C++ differs here as you need to use the "virtual" keyword in order to get dynamic dispatch - by default it hasn't so you can't modify code in base class that relies on the hasCredentials method. The above example also protects against this as the D.foo does not replace calls to foo from B.
When the method is private, it's not visible to its child. So there is no meaning of overriding it.
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:
class Base {
public void callFoo() {
foo();
}
private void foo() {
}
}
class Child extends Base {
private void foo() {
}
}
Usage is like the following:
Child c = new Child();
c.callFoo();
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.
Beyond anything said before, there's a very semantic reason for not allowing private methods to be overridden...THEY'RE PRIVATE!!!
If I write a class, and I indicate that a method is 'private', it should be completely unseeable by the outside world. Nobody should be able access it, override it, or anything else. I simply ought to be able to know that it is MY method exclusively and that nobody else is going to muck with it or depend on it. It could not be considered private if someone could muck with it. I believe that it's that simple really.
A class is defined by what methods it makes available and how they behave. Not how those are implemented internally (e.g. via calls to private methods).
Because encapsulation has to do with behavior and not implementation details, private methods have nothing to do with the idea encapsulation. In a sense, your question makes no sense. It's like asking "How is putting cream in coffee not a violation of encapsulation?"
Presumably the private method is used by something that is public. You can override that. In doing so, you've changed behavior.
Suppose I have class A
public class A
{
public void method()
{
//do stuff
}
}
Also another class B
public class B extends A
{
public void method()
{
//do other stuff
}
}
Now I have the following statements:
A a = new B();
a.method();
Is this an example of run time polymorphism? If yes, then is no binding is done for the reference a at compile time?
The compiler will tell you that this can't work, because there's no relationship between A and B that will allow you to write A a = new B();
B either has to extend A or both have to implement a common interface with void method() in it.
You could have answered this very quickly by trying it with the compiler. Be an experimentalist - it's faster than forums.
UPDATE:
It works, now that B extends A. The binding that you care about, dynamic binding, is done at runtime. The static compile time type for the variable "a" is class A; at runtime it is dynamically bound to a reference of type B. Yes, I would consider this to be an example of polymorphism.
I was waiting to put my answer to another post, into a more correctly classified problem. Your question fits the concept, I've tried to explain in detail. but, since I don't know how link answers, I'll just copy/paste the complete script here .... Kindly go through it, you'll understand everything that there is to understand about your problem, you've asked
let's say compiler has to resolve a call like this : *
A a = new AA(); // Assume AA to be some subclass of class A
a->someFunc(); // and we're invoking a method "someFunc()' on a
*.
Now, compiler will go over following steps methodically.
1.) Firstly, compiler knows the declared type of variable a, so it will check whether the declared type of object a (lets call this, class A for time being), have a method with the name someFunc() and that it must be public. This method could either be declared in class A, or it could be a derived method from one of the base class(es) of class A, but it doesn't matter to compiler and it just checks for it's existence with it's access specifier being public.
Needless to say any error in this step will invite a compiler error.
2.) Secondly, once the method is validated to be a part of the class A, compiler has to resolve the call to the correct method, since many methods could be there with same name (thanks to function overloading). This process of resolving correct method is called overloading resolution. Compiler achieves this by matching the signatures of the called method with all the overloaded methods that are part of the class. So, of all the someFunc() s only the correct someFunc() (matching the signatures with called method) will be found and considered further.
3.) Now comes the difficult part, It may very well happen that someFunc() may have been overridden in one of the subclasses of the class A (lets call this class AA and needless to say it is some subclass of A), and that variable a (declared to be of type A) may actually be referring to an object of class AA, (this is permissible in C++ to enable polymorphism). Now, if the someFunc() method is declared to be of type virtual, in base class (i.e. Class A) and someFunc() has been overriden by subclass(es) of A (either in AA or classes between A and AA), the correct version of someFunc() have to be found out by the compiler.
Now, imagine you're the compiler and you have this task of finding whether the class AA has this method. Obviously, class AA will have this method since, it is a subclass of A and public access of A in class A has already been validated in Step 1 by the compiler !!! . But Alternatively, as mentioned in previous paragraph, someFunc() may be overriden by class AA (or any other class between A and AA), which is what compiler needs to catch. Therefore, you (since, your'e playing the compiler) could do a systematic check to find the bottom-most (lowest in the inheritance tree) overridden method someFunc() starting from class A and ending at class AA. In this search, you'll look for same method signatures as was validated in overloading resolution. This method will be the method which will be invoked.
Now, you may be wondering, "What the heck", is this search done everytime ? ... Well, Not really. The compiler knows the overhead of finding this everytime, and as such, maintains a data-structure called Virtual Table for every class type. Think of virtual table, as mapping from method signatures (which are publicly accessible) to the function pointers. This virtual table is made by compiler during compilation process and is maintained in-memory during program execution. In our example, class A and class AA will both have their own virtual tables. And when compiler has to be find someFunc() in class AA (since actual object pointed by variable a is of type AA), it will simply find the function pointer through the virtual table of Class AA. This is as simple has hashing into the table and is a constant time operation.
Regards
AViD
The code example you've given isn't legal, so I guess the answer is that it's not a kind of polymorphism.
You can't assign a class to a variable of an unrelated type like that. I'm guessing that you might be intending for B to derive from A?
Is this an example of run time polymorphism?
As of the edit: yes that would be runtime polymorphism, since which method is actually executed depends on what is assigned to a.
Edit:
If method() would be static, then calling a.method() would always result in the version of A being called. However, you'd then just write A.method() and if you don't do that any decent IDE would warn you about that (because it might be misleading to call a static method on an instance).
End Edit.
Compile time polymorphism would be the overloading mechanism, i.e. the compiler decides whether to use someMethod(Number) or someMethod(Integer) depending on what it knows about the parameter that is passed (if you pass a Double or just a Number it would be the first one, if you pass an Integer it would be the second).
If yes, then is no binding is done for the reference a at compile time?
What do you mean exactly? Note that the type of a will be A so you can assign everything that extends A at runtime. The compiler will just complain if the assigned value is not an A (you might trick the compiler with a cast, but this is just evil and if this breaks your program, you have been warned ;) )
It should be
public class B extends A {
public void method()
{
//do other stuff
} }
If it were compiling, it would be the B::method() that would be called. (only if you changed your code to make the B class inherit the A class).
In this case your use your object like it was only an A, but if some methods are overidden in B, then these methods are called, instead of A's methods.
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?
You can't override a private method, but you can introduce one in a derived class without a problem. This compiles fine:
class Base
{
private void foo()
{
}
}
class Child extends Base
{
private void foo()
{
}
}
Note that if you try to apply the #Override annotation to Child.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 of override 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, allowing private methods to be overwritten will either cause a leak of encapsulation or a security risk. If we assume that it were possible, then we’d get the following situation:
Let's say that there's a private method boolean hasCredentials() then an extended class could simply override it like this:
boolean hasCredentials() { return true; }
thus breaking the security check.
The only way for the original class to prevent this would be to declare its method final. But now, this is leaks implementation information through the encapsulation, because a derived class now cannot create a method hasCredentials any more – it would clash with the one defined in the base class.
That’s bad: lets say this method doesn’t exist at first in Base. Now, an implementor can legitimately derive a class Derived and give it a method hasCredentials which works as expected.
But now, a new version of the original Base class is released. Its public interface doesn’t change (and neither do its invariants) so we must expect that it doesn’t break existing code. Only it does, because now there’s a name clash with a method in a derived class.
I think the question stems from a misunderstanding:
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)
The text inside the parentheses is the opposite of the text before it. Java does allow you to “independently implement [a private method], with the same signature, in a child class”. Not allowing this would violate encapsulation, as I’ve explained above.
But “to not allow a parent's private method to be "overridden"” is something different, and necessary to ensure encapsulation.
"Do other languages (C++ or C#) have different rules on this?"
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 a private member function as virtual, 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 fashion
protected virtual means that you should / must invoke the upper class version of the member function when overriding it
So, 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
Name lookup may associate more than one declaration with a name if it finds the name to be a function name; the declarations are said to form a set of overloaded functions (13.1). Overload resolution (13.3) takes place after name lookup has succeeded. The access rules (clause 11) are considered only once name lookup and function overload resolution (if applicable) have succeeded. Only after name lookup, function overload resolution (if applicable) and access checking have succeeded are the attributes introduced by the name’s declaration used further in expression processing (clause 5).
ISO/IEC 14882-2003 §5.2.2
The function called in a member function call is normally selected according to the static type of the object expression (clause 10), but if that function isvirtualand is not specified using aqualified-idthen the function actually called will be the final overrider (10.3) of the selected function in the dynamic type of the object expression [Note: the dynamic type is the type of the object pointed or referred to by the current value of the object expression.
A parent's private method cannot be accessed or inherited by a child class, inline 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?
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".
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:
public class PrivateOverride {
private static Test monitor = new Test();
private void f() {
System.out.println("private f()");
}
public static void main(String[] args) {
PrivateOverride po = new Derived();
po.f();
});
}
}
class Derived extends PrivateOverride {
public void f() {
System.out.println("public f()");
}
}
And the quote:
You might reasonably expect the output to be “public f( )”,
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.
It seems to be a matter of choice and definition. The reason you can't do this in java is because the specification says so, but the question were more why the specification says so.
The fact that C++ allows this (even if we use virtual keyword to force dynamic dispatch) shows that there is no inherent reason why you couldn't allow this.
However it seem to be perfectly legal to replace the method:
class B {
private int foo()
{
return 42;
}
public int bar()
{
return foo();
}
}
class D extends B {
private int foo()
{
return 43;
}
public int frob()
{
return foo();
}
}
Seems to compile OK (on my compiler), but the D.foo is not related to B.foo (ie it doesn't override it) - bar() always return 42 (by calling B.foo) and frob() always returns 43 (by calling D.foo) no matter whether called on a B or D instance.
One reason that Java does not allow override the method would be that they didn't like to allow the method to be changed as in Konrad Rudolph's example. Note that C++ differs here as you need to use the "virtual" keyword in order to get dynamic dispatch - by default it hasn't so you can't modify code in base class that relies on the hasCredentials method. The above example also protects against this as the D.foo does not replace calls to foo from B.
When the method is private, it's not visible to its child. So there is no meaning of overriding it.
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:
class Base {
public void callFoo() {
foo();
}
private void foo() {
}
}
class Child extends Base {
private void foo() {
}
}
Usage is like the following:
Child c = new Child();
c.callFoo();
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.
Beyond anything said before, there's a very semantic reason for not allowing private methods to be overridden...THEY'RE PRIVATE!!!
If I write a class, and I indicate that a method is 'private', it should be completely unseeable by the outside world. Nobody should be able access it, override it, or anything else. I simply ought to be able to know that it is MY method exclusively and that nobody else is going to muck with it or depend on it. It could not be considered private if someone could muck with it. I believe that it's that simple really.
A class is defined by what methods it makes available and how they behave. Not how those are implemented internally (e.g. via calls to private methods).
Because encapsulation has to do with behavior and not implementation details, private methods have nothing to do with the idea encapsulation. In a sense, your question makes no sense. It's like asking "How is putting cream in coffee not a violation of encapsulation?"
Presumably the private method is used by something that is public. You can override that. In doing so, you've changed behavior.