• Post Reply Bookmark Topic Watch Topic
  • New Topic

abstract type and clone() question  RSS feed

 
Greenhorn
Posts: 6
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi,

I am currently taking a Java I course and ran into something involving abstract types and clone() that I don't fully understand. The attached file compiles and runs fine when compiled as a single file. However if I break it into 3 classes i.e. Shape, Square, and TestSquare, then where I try to clone a Shape reference to a Shape or Square reference (i.e. "Shape e = (Square) d.clone();") I get a compile error that "The method clone() from the type Object is not visible". I can get it to work by changing it to "Shape e = (Shape)((Square)d).clone();" but I am trying to understand why this is needed.

Thanks,

Tony

 
author
Sheriff
Posts: 23295
125
C++ Chrome Eclipse IDE Firefox Browser Java jQuery Linux VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Tony West wrote:I am currently taking a Java I course and ran into something involving abstract types and clone() that I don't fully understand. The attached file compiles and runs fine when compiled as a single file. However if I break it into 3 classes i.e. Shape, Square, and TestSquare, then where I try to clone a Shape reference to a Shape or Square reference (i.e. "Shape e = (Square) d.clone();") I get a compile error that "The method clone() from the type Object is not visible". I can get it to work by changing it to "Shape e = (Shape)((Square)d).clone();" but I am trying to understand why this is needed.


Section 6.6.2 of the JLS. A class can only access a protected member that is declared in a class outside of the package, only if it is responsible for the implementation of the class.

http://docs.oracle.com/javase/specs/jls/se7/html/jls-6.html#jls-6.6.2


The clone() method is protected, and is declared in the Object class. The instance is not confirmed to be a Square instance (at compile time). it is only a shape instance. And hence, it can't be confirm to be responsible for the implementation of the instance.

The Shape instance obviously can't be confirmed to be a Square instance (at compile time). And the clone() method for the Shape class is part of the Object class, which is in a different package.

To make it work, you will need to cast the "d" reference to a square instance before you can use it.

Henry
 
Tony West
Greenhorn
Posts: 6
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks for the quick reply Henry! I see where you are going and understand how to make it work with the cast to Square but what confuses me is why the code above works when compiled and run as a single file? It only seems to require the extra cast when I divide it into multiple classes in the same package.

Tony
 
Henry Wong
author
Sheriff
Posts: 23295
125
C++ Chrome Eclipse IDE Firefox Browser Java jQuery Linux VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Tony West wrote:Thanks for the quick reply Henry! I see where you are going and understand how to make it work with the cast to Square but what confuses me is why the code above works when compiled and run as a single file? It only seems to require the extra cast when I divide it into multiple classes in the same package.


You need to show us the code that you are describing -- we don't know what you mean, or how, you are "dividing it into multiple classes".

Henry
 
Tony West
Greenhorn
Posts: 6
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
If I have three separate files as follows then I get compile errors as shown:




However, if I bundle all three classes into a single file I don't need to do the extra cast to Square:



So in summary I understand how to make it work. I just don't understand why as a single file I don't need the extra cast. Perhaps Java handles accessibility slightly different when the classes are combined in the same file?

Thanks,

Tony
 
Henry Wong
author
Sheriff
Posts: 23295
125
C++ Chrome Eclipse IDE Firefox Browser Java jQuery Linux VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Tony West wrote:
So in summary I understand how to make it work. I just don't understand why as a single file I don't need the extra cast. Perhaps Java handles accessibility slightly different when the classes are combined in the same file?


In your first example, the code that is calling the clone() method, is part of the TestSquare class, which is not "responsible" for the implementation of the Shape class.

In your second example, the code that is calling the clone() method, is part of the implementation of the Shape class (which of course, is "responsible" for the implementation of the Shape class).

Same rule as mentioned before. Applied in the same way. Just the results are different.

Henry
 
Tony West
Greenhorn
Posts: 6
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
OK, now I think I understand the key point I was missing. When I used a single file to contain all of the classes the main method was by definition part of the Shape class, which was the reference type for "d", thus giving it access to clone() within the Object class. So once I moved it into its own TestShape class it lost all visibility to clone() within the Object class. Then by doing the cast to Square it opened up visibility to the version of clone() within Square. Then clone() within Square was able to access clone() within Object via super.clone(). Thanks a bunch!

Tony
 
Marshal
Posts: 56600
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I always thought you were supposed to override the clone() method with public access.
 
Tony West
Greenhorn
Posts: 6
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Campbell Ritchie wrote:I always thought you were supposed to override the clone() method with public access.


I think you are right. I am just learning about Cloneable and clone(), so I was experimenting with code. I noticed that if I grouped my testing method within the same file as the Square and Shape classes, that I could call the clone() method without the extra cast. And when I separated each class to a different file i.e. Shape, Square, and TestSquare, I had to do an extra cast to get the compile to work. This had me scratching my head. What I did not initially realize was that with the single file containing all of the classes I was calling the clone() method of Object when I should have been using the extra cast to call the clone() method of the Square class (which I did override as public). In this simple test case the results were the same as I was doing a shallow copy. Kudos to Henry for showing me the light.
 
Ranch Hand
Posts: 934
4
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks Henry for wonderful explanation..

@Campbell do you mean to define clone() method in test class? I am sorry but i dint get it.

@Tony Just small thing i noticed. Package name 'Test' should be small 'test'.
 
Campbell Ritchie
Marshal
Posts: 56600
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
If you are doing good programming you would maybe not use clone() at all; Joshua Bloch in Effective Java™ page 54 is quite disparaging about it. You could download a PDF sample chapter of the earlier edition of that book; if you find it you will find part of it is about clone(). Bloch says you have to implement the Cloneable interface and use super. and a cast. That will get you a shallow clone. If any of the fields of your class is a mutable reference type you would have to use a deep clone whereby each of the fields is duplicated. This is how you can implement a shallow cloneIf you have any mutable reference types as fields you would have to copy them too; that may be incompatible with final fields. What about a copy constructor? Same class as before but minus the cloningNew you can say new Foo(f)
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!