5

みなさん、こんにちは。

以下が機能しない理由を教えてくれるJavaハッカーがいるかどうか疑問に思っています。

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

コードはコンパイルできますが、実行時に ClassCastException をスローすることにします D=

編集:おっと、本当に迅速な返信。みんなありがとう!したがって、この方法を使用してダウンキャストできないようです... Javaでダウンキャストを行う他の方法はありますか? ChildN各クラスを上書きすることも考えましcopy()たが、余分な定型コードを追加することに熱心ではありませんでした。

4

7 に答える 7

9

これをやろうとしているようなものです:

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

そして、次のことを試みます。

  String s = ( String ) copy();

ParentクラスとChildNクラスは、 ObjectStringと同じ関係にあります。

それを機能させるには、次のことを行う必要があります。

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

つまり、「コピー」メソッドをオーバーライドして、正しいインスタンスを返します。


編集

あなたの編集によると。それは実際に可能です。これは 1 つの可能な方法です。

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

そうすれば、各サブクラスで「コピー」メソッドをオーバーライドする必要がなくなります。プロトタイプのデザインパターンです。

ただし、この実装を使用すると、2 つのチェック済み例外に注意する必要があります。問題なくコンパイルおよび実行される完全なプログラムを次に示します。

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 );
    }
}
于 2008-12-30T20:39:06.663 に答える
6

キャストは効果的にこれをやろうとしています:

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

(実行時に実行するようにキャストを作成していますが、 になるため、そのようにorig.getClass()なりますChildN.class) ただし、orig.copy()ChildN のインスタンスを返すのではなく、 just のインスタンスを返すParentため、 にキャストすることはできませんChildN

于 2008-12-30T20:34:22.600 に答える
4

ChildN が copy() をオーバーライドして ChildN のインスタンスを返さない場合、parent 型のオブジェクトを ChildN 型にダウンキャストしようとしています。

于 2008-12-30T20:35:04.657 に答える
2

Class#isInstance() が false を返す場合、java.lang.Class#cast(Object) は ClassCastException をスローします。そのメソッドの javadoc から:

指定された Object が、この Class によって表されるオブジェクトと代入互換性があるかどうかを判断します。このメソッドは、Java 言語の instanceof 演算子と動的に同等です... 具体的には、この Classオブジェクトが宣言されたクラスを表す場合、このメソッドは true、指定された Object引数が、表されたクラス (またはそのサブクラス) のインスタンスである場合に戻ります。それ以外の場合は返し falseます。

Parent は child のサブクラスではないため、isInstance() は false を返し、cast() は例外をスローします。これは最小の驚きの原則に違反する可能性がありますが、文書化されている方法で機能しています - cast() はダウンキャストではなくアップキャストのみ可能です。

于 2008-12-30T20:42:50.710 に答える
2

オブジェクトのコピー/クローンが必要なだけかもしれません。

その場合、Cloneable インターフェースを実装し、必要に応じて clone() をオーバーライドします。

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

これは、「copy()」メソッドが Java の方法で実行しようとしたこととまったく同じです。

(はい、空想的なイントロスペクション ゲームも実行できますが、パブリックなデフォルト コンストラクターがないと、これらのメソッドは失敗するか、見苦しくなります。どのようなコンストラクターを持っていても、クローンはどのような場合でも機能します。)

于 2008-12-31T01:15:38.053 に答える
1

(コメントにコードを追加できないので、ここに追加します)

Cloneableについて:Cloneableを実装している場合は、次のように実装します。呼び出すのがはるかにきれいです...

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

[編集:他の人が使用しているのも見た

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

キャッチブロックで。]

于 2008-12-31T21:08:18.520 に答える
0

ダウンキャストが機能しない理由は、親オブジェクトを子型にキャストすると、親オブジェクトで子型のメソッドを呼び出す方法がないためです。しかし、それは逆に機能します...

于 2009-01-04T17:41:16.243 に答える