What Protected Really Means

The “protected” access modifier says the member is visible to any classes in the same package, and to subclasses everywhere. The same package part is clear enough: your code is never in the same package as java.lang.Object.clone(). The “subclasses everywhere” part is more accurately expressed as a protected member can be accessed from within a class through references that are of at least the same type of the class. Consider this example, which uses a protected field called “teeth”, which is simpler to follow than the clone() method:

package animals;
class Mammal {protected int teeth;  }

package pets;
class Cat extends Mammal { }

class Dog extends Mammal {
    Cat housemate = new Cat();
    int cats_teeth = housemate.teeth; // NO!! field is protected.
}

class Dalmatian extends Dog { }

Cat and Dog both inherit the protected field teeth from Mammal. Since Mammal is in a different package, the subclass rule applies. That stipulates that code in the Dog class can access the protected teeth field only through a reference that is Dog or a subtype of Dog, like Dalmatian.

Code in the Dog class cannot access the protected field using a reference to Cat. Cat can access the protected field using a reference to Cat. If you have a reference to Mammal, and if you can successfully cast it to Dog, you can use that Dog value inside Dog to access the field. You can't use the Mammal reference inside Dog to access the field.

This rule is aimed at making sure that protected instance members are accessed only by the part of the class hierarchy they belong to, and not by siblings. It's a funny rule because unlike public, private, or package access, a line of code that accesses a protected member can be valid in one class and not valid in the next class you write in the same package. Even when both classes are subtypes of the class with the protected member! The rule doesn't apply to static protected variables and methods. Those are accessible from any child class, since there is no “object” through which to access them.

The member in question is Object.clone in package java.lang. Clearly, my class C is not in package java.lang, and is not a subclass of class B. Therefore class C cannot access B's clone(). This means that a method can clone its own objects inside its own class and nobody in other packages can, which is not terrifically useful.

The fix? Just override Object's-version-of-clone in the class that implements Cloneable and make the method public! You can give the same or more generous access when you override a method.

Furthermore, Java now has “covariant return types”. That means when you override a method, you don't have to return the exact same type that the parent method does. You may now return an <ITALICS>subtype<END ITALICS> of the type the parent returns. So you usually make your version of clone() public, and also return precisely the correct type instead of the parent type Object:

public class MyClass implements Cloneable {
          public MyClass clone() throws CloneNotSupportedException {
               return (MyClass) super.clone();
          }
}

When you override clone() to make it public, that will allow any class to call B's clone() method. The usual implementation for clone is to call the superclass clone(). Then you can make any other adjustments you want, such as cloning objects that are referred to by fields in the Cloneable class and so on.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.137.172.115