Hi, I'm just wondering why a method with friendly access can be overrided with public access in the child? Private does not work though. Parent: void method(); Child: public void method(); // OK Child: private void method(); // ERROR Thanks in advance.
It is allowed to override a method in a subclass and to give it "more" access than it already has in the superclass. But it is not allowed to restrict the access the method has in the superclass. If a method is declared public in the superclass, you have no choice but to declare it public in the subclass also. Beware of the following trap, though: If a method is declared private in a superclass, there is no way to override it in a subclass. This means that you can have the same method in the subclass with any access modifier you wish but the method in the subclass will not be considered as an override of the method in the superclass. Please check out JLS 220.127.116.11 Requirements in Overriding and Hiding (3rd paragraph). [ December 26, 2002: Message edited by: Valentin Crettaz ]
Howdy all -- let's talk about the idea of "contracts". As in, "something you promise to do, and that everyone can trust". When a superclass Dog has a public method bark(), anyone with a Dog reference thinks they can ask that Dog to bark. But then here comes subclass Beagle (think: Snoopy), and it wants to override the bark() method to make it a more Beagle-specific bark. Remember that polymorphicially, the following is legal (and desirable): Dog d = new Beagle(); d.bark(); And because of the magic of polymorphism, the OBJECT type, not the REFERENCE type determines which version of bark() will be called. In this case, because Beagle has overridden the bark() method, and because it is truly a Beagle on the heap, the Beagle's version of bark() will run, even though it is a Dog reference type. No problem, right? Dog d = new Beagle(); is legal in Java because "A Beagle IS-A Dog and is therefore guaranteed to do anything a Dog can do." So anyone with a Dog reference can feel confident and assured that no matter WHAT is out there on the other end of that reference (in other words, no matter *which* kind of Dog subclass is on the heap), that object can respond to all the accessible Dog class methods. We know this works because of inheritance. Any subclass of Dog inherits the accessible methods of Dog, so any subclass of Dog *has* the Dog methods, regardless of whether that subclass overrides the methods or simply inherits them. Or does it? What if the Beagle class overrode the bark() method and made it <gasp> private? Here you are minding your own business with a Dog reference, thinking everything is wonderful. Dog d = new Beagle(); But then... to your horror... d.bark(); // BLOWS UP! Suddenly, and without warning, you have a Dog that won't bark()! That just cannot be allowed. So do not be thinking that the JVM (or compiler) will simply say, "No problem, I will just go back to the one in class Dog and call *that* version of bark()" Nope, polymorphism always prevails, so it will always be the Beagle's overridden version that will be invoked. So because Beagle IS-A Dog, Beagle must "agree to the contract". Beagle must fulfill the true state of Dogness by implementing a bark() method that can be called by ANYONE who has a Dog reference. In other words, If Beagle IS-A Dog, then Beagle better ACT like a Dog. And that means, his behavior (methods) must work for anyone who has a Dog reference. So, Beagle cannot make an overridden method more restrictive, because it would break the contract. If that were allowed, then someone with a Dog reference would never know for certain if all Dog methods would really be callable. ("Oh no, I think it is a Dog, but what if it's really a Dalmation, and it overrode a method and made it more restrictive?") That ALSO explains why you must not override a method and throw new -- or more specific -- checked exceptions. You would have the same problem. If Beagle overrides bark() and makes it throw a (checked) IllegalBarkStateException, which was NOT declared by the Dog version of the bark() method, then the poor Dog holder (Dog d = new Beagle()) will once again THINK that he is safe in calling a bark() method on any Dog subclass type that happens to be at the other end of the Dog reference, but then suddenly the Beagle sneaks in and throws an exception that the Dog reference variable user was not expecting. And one last thing... you cannot do anything in a subclass that will "break" a contract laid out by the superclass, BUT... you can certainly be MORE friendly, MORE open, LESS risky. So you can always make the method more accessible because the Dog reference variable holder will not be harmed in any way by the Beagle declaring a more accessible bark(). All the Dog holder cares about is that the darn thing can bark! And the Dog holder will NOT be unhappy that the Beagle's bark() method does not declare (because it does not THROW) the exceptions of the superclass version of the method. Bottom line: A subclass must never violate the contract defined by the superclass. Because polymorphism always allows you to refer to a subclass object using a superclass reference variable, the subclass object must always be able to do EVERYTHING that the superclass type defines, and without SURPRISES. So, no new (or broader) checked exceptions, and no making the method more restrictive. But the subclass can be friendlier, and less risky with it's overriding methods, by having a more accessible modifier, and NOT declaring the same (or any) exceptions. Cheers, Kathy RanchPerson r = new Cowgirl(); r. cleanBarn(); Cowgirl MUST be able to do the cleanBarn method, but you better believe I'm going to override that baby and make it... empty. The contract only says I must HAVE a callable cleanBarn method. The contract does *not* say how I am supposed to implement it