Reputation: 3688
I am having problems trying to figure out how to call the clone method from a object which its reference is of an interface type.
Basically this is what I need to do.
for(Interface obj: objs)
array.add(obj.clone());
I do not know what is the obj type, I just know it implements Interface, and when I try this code I get
"The method clone() is undefined for the type Interface".
And when I try to put clone() on my Interface I get:
"The method clone() of type Interface must override or implement a supertype method", because I am using @Override tag.
My intention is to use Object.clone() in the end. But I just cant figure this out.
Any thoughts?
The real code:
public interface Caracteristica {
@Override <---problem
public Object clone() throws CloneNotSupportedException;
@Override <---fine
public boolean equals(Object obj);
}
private final void setCaracteristicas(ArrayList<Caracteristica> caracteristicas) {
this.caracteristicas = new ArrayList<>();
for(Caracteristica caracteristica: caracteristicas)
this.caracteristicas.add((Caracteristica)caracteristica.clone());
}
Upvotes: 0
Views: 212
Reputation: 76908
Basically, clone()
and the Cloneable
interface is broken in a number of ways and even according to Josh Bloch it should be avoided. (See: http://www.artima.com/intv/bloch13.html)
Add a new method to your interface that returns the interface type and implement that in your class to make copies.
Edit to Add: Ignoring the above statement, the reason it is telling you that the @Override
annotation in your interface is incorrect is because ... it is. You're not extending an interface that defines clone()
.
Interfaces don't extend Object
; Section 9.2 of the JLS tells us:
If an interface has no direct superinterfaces, then the interface implicitly declares a public abstract member method m with signature s, return type r, and throws clause t corresponding to each public instance method m with signature s, return type r, and throws clause t declared in Object, unless a method with the same signature, same return type, and a compatible throws clause is explicitly declared by the interface.
clone()
is protected
in Object
so it is not implicitly included. If your IDE said to add the @Override
tag, report that as a bug, because it's wrong.
equals()
, on the other hand, is public
in Object
, therefore it is included in the implicit superinterface unless you override it.
If you are bound and determined, this will work though it's really ugly due to the confusion created by clone()
being defined both in Object
and MyInterface
and having it return the interface type (which is allowed because it's a covariant type):
public interface MyInterface {
MyInterface clone();
void doSomething();
}
public class MyClass implements MyInterface {
@Override
public void doSomething() {
System.out.println("Hi");
}
@Override
public MyInterface clone() {
return new MyClass();
}
public static void main(String[] args) {
MyInterface mi = new MyClass();
MyInterface mi2 = mi.clone();
mi2.doSomething();
}
}
Upvotes: 3
Reputation: 44439
Object.clone()
is protected
, you can't call it from outside the class or its subclasses unless they explicitly change the access modifier to public
thus there is no guarantee an object has a visible clone()
method.
You have to define this in an interface or override it in a baseclass instead.
Upvotes: 2