简体   繁体   中英

Using Clone() with polymorphism from interface in java

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());
 }

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();
    }

}

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM