Falls Sie frei Erweiterung zu verwenden, anstatt der Implementierung, dann könnte man, dass diese Art und Weise tun:
public interface Thing { ... }
public abstract class Copyable {
public final Copyable copy() {
Copyable clone = createCopy();
if (clone.getClass() != getClass())
throw new RuntimeException("Copy has wrong type!");
return clone;
}
protected abstract Copyable createCopy();
}
Und es dann gerne verwenden:
public class Test extends Copyable implements Thing {
public String content = null;
@Override
public Copyable createCopy() {
Test clone = new Test();
clone.content = this.content;
return clone;
}
}
/*code somewhere*/ {
Test t1 = new Test();
t1.content = "Hello world!";
Test t2 = (Test)t1.copy();
System.out.println(t2.content);
}
Ein Problem dabei ist dass Copyable
keine Schnittstelle ist. Dies kann jedoch ohne großen Aufwand, wie im Beispiel gezeigt, verwendet werden, aber die verwendete Klassenprüfung wird nicht auf Sprachenebene unterstützt. Mit anderen Worten, die createCopy
abstrakte Methode ist nicht auf die Klasse beschränkt, die sie kopiert, und all das ist Sache des Programmierers, der die Klasse Copyable
oder eine Klasse erweitert, die sie erweitert.
Die positive Seite, ist, dass, wenn Sie die .copy()
auf das Objekt aufrufen, es ein Objekt zurückgegeben werden muss, das selbe wie sich selbst ist. Anstelle einer Ausnahme können Sie null
zurückgeben, wenn Sie möchten. Dann hast du gut oder nichts.
Aber um ehrlich zu sein, ich verstehe nicht wirklich, warum Ihre createCopy
lokale Methode einen Parameter hat. Es könnte sein, dann eine statische Methode ... altrough ich kann nicht einmal vorstellen, was in diesen Codeblock gehen würde:
static <X extends Thing> X copy(X object) { ... }
können Sie die pratice mit einer statischen generischen Methode und das Ergebnis wird etwas freundlicher kombinieren könnten :
public interface Thing extends Cloneable {
public static <X extends Thing> X copy(X thing) {
Object clone = thing.clone();
if (clone.getClass() != getClass())
throw new RuntimeException("Copy has wrong type!");
return (X)clone;
}
}
public class ThingA implements Thing {
public Object clone() { ... }
}
/*code somewhere*/ {
ThingA a1 = new ThingA();
ThingA a2 = Thing.copy(a1);
}
Dennoch wird das Klonierungsverfahren durch eine Ausnahme geregelt statt Sprache Beschränkung, aber ich denke, das ist weit die beste Lösung ist.
Dies erlaubt ihm immer noch genau das zu tun, was er nicht will. Generics hindert Sie nicht daran, nur einen Typ von Klasse zu verwenden, da dies das genaue Gegenteil von Generika ist. – giorashc