Granny's Programming Pearls
"inside of every large program is a small program struggling to get out"
JavaRanch.com/granny.jsp
  • Post Reply Bookmark Topic Watch Topic
  • New Topic

Why is Object's clone( ) method 's access modifier "protected"?  RSS feed

 
Ranch Hand
Posts: 33
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I don't understand why the clone( ) method in Object class is set as protected. I did some research online and the most common answer is that by setting the access modifier as protected, you can't call clone( ) in every object. But isn't a protected method still accessible to the class's subclasses, and since every class is the subclass of Object,you can call clone( ) in every object? I understand that only those classes that implement Cloneable can use clone( ) without throwing a CloneNotSupportedException, but that still doesn't explain why clone( ) is set as protected, since clone ( ) method is declared in Object class but not the Cloneable interface. Any help will be greatly appreciated.
 
Ranch Hand
Posts: 51
2
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Citation from Effective Java book:
"The Cloneable interface was intended as a mixin interface for objects to advertise that they permit cloning. Unfortunately it fails to serve this purpose ... This is a highly atypical use of interfaces and not one to be emulated ... In order for implementing the interface to have any effect on a class, it and all of its superclasses must obey a fairly complex, unenforceable and largely undocumented protocol"
 
Marshal
Posts: 56605
172
  • Likes 2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
If clone() is protected, then you can call it in any object of any class, but you can only call it inside the same object. If you override it so as actually to do anything, you change its access to public.

I would follow MS' suggestion: believe Joshua Bloch and find different ways to copy your objects.
 
Ranch Hand
Posts: 231
12
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The clone() method is not private or package-private because these access modifiers restrict inheritance and we want the clone() method to be inherited by every subclass in every package:
  • private disables inheritance from all subclasses
  • package-private disables inheritance from subclasses outside the same package

  • The clone() method is not public because we want to restrict access:
  • we want it to be accessible to every subclass in every package i.e. we want it to be either reused by a subclass or specialized (overridden or hidden) by a subclass
  • we don't want it to be accessible to every class in every package because based on the principle of least privilege, a module should be able to access only information and resources that are necessary for its legitimate purpose


  •  
    Edwardd Lee
    Ranch Hand
    Posts: 33
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Thanks for all your responses!
    If clone() is protected, then you can call it in any object of any class, but you can only call it inside the same object.
    Can you elaborate on the difference between calling a method in any object of any class and calling it inside the same object?

    we don't want it to be accessible to every class in every package
    But isn't every class the subclass of Object? Therefore every class can still access clone( ).
     
    author
    Sheriff
    Posts: 23295
    125
    C++ Chrome Eclipse IDE Firefox Browser Java jQuery Linux VI Editor Windows
    • Likes 2
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Edwardd Lee wrote:
    we don't want it to be accessible to every class in every package
    But isn't every class the subclass of Object? Therefore every class can still access clone( ).

    No. Classes that are not in the same package, must also follow the "responsible for implementation" rule.

    https://docs.oracle.com/javase/specs/jls/se8/html/jls-6.html#jls-6.6.2

    This means that any code (in a class) must use an reference that IS-A the calling class. Otherwise, as you mentioned, any class can access any other subclass of the protected field, even if it is not a subclass of the instance that it is accessing.

    And of course, this rule only applies when the class is not in the same package, as the protected field. So, any class in the "java.lang" package, should be able to access the clone() method, of any class.

    Henry
     
    Campbell Ritchie
    Marshal
    Posts: 56605
    172
    • Likes 1
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Henry Wong wrote:. . . any class in the "java.lang" package, should be able to access the clone() method, of any class.

    Henry
    Just as well we can't get into the java.lang package to access such clone() methods :wink;
     
    Daniel Cox
    Ranch Hand
    Posts: 231
    12
    • Likes 1
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Edwardd Lee wrote:
    we don't want it to be accessible to every class in every package
    But isn't every class the subclass of Object? Therefore every class can still access clone( ).

    When dealing with the Object class, these 2 statements are the same:
  • every subclass in every package
  • every class in every package

  • When dealing with any other class, the 2 statements are not the same.

    So every class in every package can access the clone() method declared in the Object class, but if class Cat overrides this method, only subclasses of class Cat (in every package) can access the overridden clone() method. They do so via inheritance.
     
    Edwardd Lee
    Ranch Hand
    Posts: 33
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Oh I finally understand. So the reason why clone( ) is set to protected is to make it useful for users who choose to override this method. protected disables objects from different packages that are no subclasses to access the user-overriden method. The initial design to give protected access modifier to clone() byJava developers was with overriding purpose in mind.

    At the same time, you can still access the default, non-overriden clone () method class from Object class in any Cloneable objects since every object is the subclass of Object.

    I hope my understanding is correct. Thanks again for all the responses.
     
    Edwardd Lee
    Ranch Hand
    Posts: 33
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Edwardd Lee wrote:
    At the same time, you can still access the default, non-overriden clone () method class from Object class in any Cloneable objects since every object is the subclass of Object.


    Oops I meant to say clone( ) method instead of clone( ) method class. I can't seem to edit my post so I will just correct it here...
     
    Daniel Cox
    Ranch Hand
    Posts: 231
    12
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Edwardd Lee wrote:I hope my understanding is correct.

    I think your understanding is correct. 
     
    Campbell Ritchie
    Marshal
    Posts: 56605
    172
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Edwardd Lee wrote:. . . I can't seem to edit my post . . .
    But I can, so I shall strike out the error.
     
    Daniel Cox
    Ranch Hand
    Posts: 231
    12
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Edwardd Lee wrote:The initial design to give protected access modifier to clone() byJava developers was with overriding purpose in mind.

    Just one more thing. The protected access modifier is not used with only overriding in mind. It can be used with hiding in mind.

    In this code, the field age, the method play() and the class Toy cannot be overridden in a subclass but they can be hidden in a subclass. The protected access modifier is used with inheritance and possible hiding in mind.

     
    • Post Reply Bookmark Topic Watch Topic
    • New Topic
    Boost this thread!