Javaのポリモーフィズムを理解しようとしていますが、オブジェクトのダウンキャストについて1つ質問があります。この例では、スーパークラスの動物から継承する2つのサブクラスDogとCatがあるとします。
私が理解したことから、オブジェクトをダウンキャストする唯一の方法は、このオブジェクトがすでに次のように適切なタイプである場合です。
Animal a = new Dog();
Dog d = (Dog) a;
これは正しく機能しますか?
しかし、それが何であるかを知らずに通常の動物を作成し、それを知ったときにそれをキャストしたい場合はどうすればよいですか?
Animal a = new Animal();
Dog d = (Dog) a;
これは実行時にClassCastExceptionをスローしますよね?
私がそれを行うために見つけた唯一の方法は、通常の動物から犬を作成する新しいDogコンストラクターを作成することです。
Animal a = new Animal();
Dog d = new Dog(a);
と
public Class Dog extends Animal{
public Dog(Animal a){
super(a);
}
}
だから私の質問は、これをどのように行うべきかということです。
どうもありがとう! nbarraille
非ローカル条件に応じて変化する可能性のあるタイプのインスタンスを作成する場合は、 Abstract Factory を使用します(デザインパターンの本で説明されています)。
最も単純な形式では:
interface AnimalFactory {
Animal createAnimal();
}
class DogFactory implements AnimalFactory {
public Dog createAnimal() {
return new Dog();
}
}
参照の静的タイプとオブジェクトの動的タイプには違いがあることにも注意してください。 Animal
参照がある場合でも、元のオブジェクトがDog
の場合は、Dog
のように動作します。
オブジェクトが実際にあるクラスにのみキャストする必要があるため、Dog
を拡張するAnimal
がある場合は、それをAnimal
にキャストできます(1つであるため)ただし、すべてのAnimal
がDog
sであるとは限らないため、Animal
をDog
にキャストしないでください。 Dog
クラスには、Animal
クラスによって実装されていない追加のフィールドがある可能性があるため、キャストは意味がありません(これらの値を何に初期化するのですか?)。
Javaは強く型付けされた言語であるため、オブジェクトをキャストできるのは、オブジェクトの拡張元の型(スーパークラスまたはインターフェース)のみです。
あなたが「それを偽造」したとしても、例えばすべてのクラスのメソッドとフィールドをコピーします。オブジェクトを拡張しない型にキャストすることはできません。
public class Foo{
public String phleem;
public void bar(){
}
}
public class Bar{
public String phleem;
}
public interface Baz{
public void bar();
}
上記のコードを考えると、Foo
オブジェクトをBar
またはBaz
のいずれかにキャストすることはできませんが、クラス構造はキャストできることを示唆しているようです。継承は含まれないため、ClassCastException
がスローされます。
ここではダウンキャストについて話しているので、このシナリオでは常にスーパークラスを参照として使用し、子オブジェクトをそれによって指す必要があります。この米ドルは基本的に工場のパターンです。