User 965
User 965

Reputation: 189

Java cloning with super and sub classes

I have a two simple Java classes and I am trying to understand more about cloning and how to cast between different levels of classes. This is the superclass Vehicle.

public class Vehicle implements Cloneable 
{
     public int x;

     public Vehicle(int y) { 
          x = y;
     }

     @Override public Object clone() { 
      Object result = new Vehicle(this.x);
      // Location "A"
      return result;
    }
}

And this is the subclass Truck

public class Truck extends Vehicle 
{
   private int y;

   public Truck(int z) {
       super(z); 
       y = z;
   }

   @Override public Object clone() {
      Object result = super.clone();
      System.out.println(result.getClass());
      ((Truck) result).y = this.y; 
      return result; 
    }
}

I am trying to get a copy of Truck while using the superclass to clone but having issues with downcasting not being allowed. I am not really sure how to fix this or where the error is.

I would like to have: Truck a = new Truck(1) and Truck b = a.clone() become the same object.

Upvotes: 0

Views: 1978

Answers (2)

clabe45
clabe45

Reputation: 2454

When you cast from one class to another, you are not changing the actual object, but making it accessible in a different way.

class A { public int x; }
class B extends A { public int y; }
A a = new A();
B aB = new B();
System.out.println(aB); // A@...
System.out.println(aB.y); // throws an error

When you call super.clone(), it creates a Vehicle instance, and Vehicle instances do not have y.

Instead, you probably want to initiate the object and not call super.clone() in Truck.clone:

    return new Vehicle(this.y);

Upvotes: 0

shmosel
shmosel

Reputation: 50716

You're misusing clone(). All the instantiation and field copying is done by the super implementation when you implement Cloneable. Your Vehicle implementation should look like this:

@Override
public Vehicle clone() {
    try {
        return (Vehicle)super.clone();
    } catch (CloneNotSupportedException e) {
        throw new AssertionError();
    }
}

And you can optionally override it in Truck like this:

@Override
public Truck clone() {
    return (Truck)super.clone();
}

Upvotes: 3

Related Questions