Frage

Hullo alle,

Ich frage mich, ob es Java -Hacker gibt, die mich darauf hinweisen können, warum Folgendes nicht funktioniert:

public class Parent {
    public Parent copy() {
       Parent aCopy = new Parent();
       ...
       return aCopy;
    }
}

public class ChildN extends Parent {
    ...
}

public class Driver {
     public static void main(String[] args) {
         ChildN orig = new ChildN();
         ...
         ChildN copy = orig.getClass().cast(orig.copy());
     }
}

Der Code ist sehr glücklich zu kompilieren, beschließt aber, eine ClassCastException zur Laufzeit zu werfen d =

Bearbeiten: Whoah, sehr schnelle Antworten. Danke Leute! Es scheint also, dass ich mit dieser Methode nicht downcast kann ... Gibt es eine andere Möglichkeit, in Java heruntergefahren zu werden? Ich habe darüber nachgedacht, jeden zu haben ChildN Klassenüberschreibung copy(), aber war nicht begeistert, den zusätzlichen Kesselplattencode hinzuzufügen.

War es hilfreich?

Lösung

(Ich kann keinen Code in einem Kommentar hinzufügen, also werde ich hier hinzufügen)

In Bezug auf das Klonable: Wenn Sie Klonable implementieren, implementieren Sie es wie folgt. viel sauberer zu rufen ...

public class Foo implements Cloneable {
    public Foo clone() {
        try {
            return (Foo) super.clone();
        } catch (CloneNotSupportedException e) {
            return null; // can never happen!
    }
}

Bearbeiten: Ich habe auch gesehen, wie andere Leute verwendet werden

throw new AssertionError("This should never happen! I'm Cloneable!");

im Fangblock.

Andere Tipps

Ist wie der Versuch, dies zu tun:

  public Object copy(){
       return new Object();
  }

Und dann versuchen Sie:

  String s = ( String ) copy();

Dein Elternteil Klasse und Kindn Klasse haben die gleiche Beziehung wie Objekt und Saite

Damit es funktioniert, müssten Sie Folgendes tun:

public class ChildN extends Parent {
    public Parent copy() {
        return new ChildN();
    }
}

Das heißt, überschreiben Sie die "Kopier" -Methode und geben Sie die richtige Instanz zurück.


BEARBEITEN

Gemäß Ihrer Bearbeitung. Das ist eigentlich möglich. Dies könnte ein möglicher Weg sein:

public class Parent {
    public Parent copy() {
        Parent copy = this.getClass().newInstance();
        //...
        return copy;
    }
}

Auf diese Weise müssen Sie die "Kopier" -Methode in jeder Unterklasse nicht überschreiben. Dies ist das Prototyp -Designmuster.

Mit dieser Implementierung sollten Sie jedoch zwei überprüfte Ausnahmen wissen. Hier ist das vollständige Programm, das ohne Probleme kompiliert und ausgeführt wird.

public class Parent {
    public Parent copy()  throws InstantiationException, IllegalAccessException  {
       Parent copy = this.getClass().newInstance();
       //...
       return copy;
    }
}
class ChildN  extends Parent {}

class Driver {
     public static void main(String[] args) throws  InstantiationException ,  IllegalAccessException  {
         ChildN orig = new ChildN();
         ChildN copy = orig.getClass().cast(orig.copy());
         System.out.println( "Greetings from : " + copy );
    }
}

Die Besetzung versucht effektiv, dies zu tun:

ChildN copy = (ChildN) orig.copy();

(Es arbeitet die Besetzung aus, um zur Ausführungszeit aufzutreten, aber genau das wird es sein, weil orig.getClass() wird sein ChildN.class) Jedoch, orig.copy() Gibt keine Instanz von Childn zurück, es gibt eine Instanz von Just zurück Parent, also kann es nicht gegossen werden ChildN.

Wenn Childn Copy () nicht überschreibt, um eine Instanz von Childn zurückzugeben

java.lang.class#cast (Object) löst eine ClassCastException aus, wenn die Klasse#isinstance () false zurückgibt. Aus dem Javadoc für diese Methode:

Bestimmt, ob das angegebene Objekt zu Zuordnungskompatibel mit dem von dieser Klasse dargelegten Objekt ist. Diese Methode ist das dynamische Äquivalent der Java -Sprachinstanz des Operators ... speziell, wenn dies Class Objekt repräsentiert eine deklarierte Klasse, diese Methode kehrt zurück true Wenn der angegebene Object Argument ist eine Instanz der dargestellten Klasse (oder einer seiner Unterklassen); es kehrt zurück false Andernfalls.

Da Eltern keine Unterklasse des Kindes sind, gibt Isinstance () false zurück, also macht cast () die Ausnahme aus. Dies mag gegen das Prinzip des geringsten Erstaunens verstoßen, aber es funktioniert so, wie es dokumentiert wird - Cast () kann nur upcast, nicht niedergeschlagen.

Könnte es sein, dass Sie einfach eine Kopie/einen Klon Ihres Objekts möchten?

Implementieren Sie in diesem Fall die klonbare Schnittstelle und überschreiben Sie Clone () nach Bedarf.

public class Parent implement Cloneable {
   public Object clone() throws CloneNotSupportedException {
     Parent aCopy = (Parent) super.clone();
   ...
   return aCopy;
   }
}

public class ChildN extends Parent {
    ...
}

public class Driver {
     public static void main(String[] args) {
         ChildN orig = new ChildN();
         ...
         ChildN copy = orig.getClass().cast(orig.clone());
     }
}

Dies tut genau das, was Ihre "Copy ()" -Methode auf Java -Weise versucht hat.

(Ja, Sie könnten auch ausgefallene Introspection-Spiele machen, aber diese Methoden scheitern oder werden hässlich, sobald Sie keinen öffentlichen Standardkonstruktor haben. Klon arbeitet in jedem Fall, egal welche Konstruktoren Sie haben.)

Der Grund, warum die Herunterbindung nicht funktioniert, liegt darin, dass Sie, wenn Sie ein übergeordnetes Objekt an einen Kindertyp werfen, auf keinen Fall die Methoden des Kindertyps auf das übergeordnete Objekt aufrufen können. Aber es funktioniert in der anderen Seite ...

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top