up-casting & down-casting

4532 ワード

1.概要
1)定義
up-casting:スーパータイプcasting.つまり、子タイプのオブジェクトを親タイプのオブジェクトとして扱うことができる.
down casting:サブタイプのcasting.すなわち、上播オブジェクトをchild classタイプのオブジェクトとして再処理することができる.
2)注意事項
castingはオブジェクト自体を変えるのではなく、異なるラベルを貼るだけです.たとえば、Dogオブジェクトを作成してAnimalオブジェクトにアップグレードしても、そのオブジェクトはDogオブジェクトです.ただし、このオブジェクトは他のAnimalオブジェクトと同じように処理され、Dog propertyは非表示になります.
これは、Animalオブジェクトグループがある場合、どの動物がmeow()またはbark()を必要とするか分からないため、AnimalオブジェクトはChild classのpropertyまたはmethodにアクセスできないためである.
3)違い
オンデマンドは常に許可されていますが、オンデマンドにはタイプチェックが必要で、ClassCastExceptionを放出することができます.
upcasting
upcastingは安全です.これは、Dogオブジェクトを常にAnimalオブジェクトに変換し、Animalのすべてのプロパティとメソッドを使用できることを意味します.
downcasting
downcastingでは、オブジェクトのruntime typeは実際に何ですか?downcastingが安全ではないのは、child classのメソッドやプロパティで実際に実装したい場合があるからです.これは次の例で見ることができます.
downcastメソッド
Animal animal = new Animal();
Dog dog = animal;
このコードはコンパイル時にエラーを引き起こす可能性があります.これは、Parent classのオブジェクトがchild classのオブジェクトとして指定されていないためです.
Animal animal = new Animal();
Dog dog = (Dog) animal;
ここでコンパイル時のエラーは発生しませんが、実行時にClassCastExceptionが発生します.動物のruntimetypeはAnimalなので、実行時に鋳造しようとするとClassCastExceptionが発生します.動物はDogではないからです.
Animal animal = new Dog();
Dog dog = animal;
ここでコンパイル中にエラーが再び発生しました.アニマルをDogに変換する方法が明示されていないからです.
Animal animal = new Dog();
Dog dog = (Dog) animal;
このコードがdowncastを正しく行う方法です.
2.例
public class Animal {
    public void walk()
    {
        System.out.println("Walking Animal");
    }
}
class Dog extends Animal {  
    public void walk()
    {
        System.out.println("Walking Dog");
    }
    public void sleep()
    {
        System.out.println("Sleeping Dog");
    }
}
class Demo {    
    public static void main (String [] args) {  	
    	Animal a = new Animal();
    	Dog d = new Dog();             
    	a.walk();
    	d.walk();
    	d.sleep();
    	
    	//upcasting  
        Animal a2 = (Animal)d;
        a2.walk();
        //a2.sleep();  error
        
        //downcasting
        Animal a3 = new Dog();
        //Dog d2 = a3;  //compile time error
        Dog d2 = (Dog)a3;
        d2.walk();
        d2.sleep();
        
        //Run time error: Animal cannot be cast to Dog
        Animal a4 = new Animal();
        //Dog d3 = (Dog)a4;
        //d3.walk();
        //d3.sleep();
    }
}
Output
Walking Animal
Walking Dog
Sleeping Dog
Walking Dog
Walking Dog
Sleeping Dog
3.なぜParent p=new Child()を使うのか
1)メリット
upcastingを使う理由は、マルチフォームだからです.オブジェクトの正確なランタイムタイプが分からない場合は、そのオブジェクトを使用できます.これは、Parentリファレンス変数が任意のサブクラスオブジェクトを持つことができるためです.
2)例
class Parent {
	void work(){
		System.out.println("working");
	}
}
class Child1 extends Parent{
	void relax(){
		System.out.println("relaxing 1");
	}
}
class Child2 extends Parent{
	void relax(){
		System.out.println("relaxing 2");
	}
}
class Child3 extends Parent{
	void relax(){
		System.out.println("relaxing 3");
	}
}
class Child4 extends Parent{
	void relax(){
		System.out.println("relaxing 4");
	}
}
public class Demo {    
    public static void main (String [] args) {
    	List<Parent> lst = new ArrayList<Parent>();
    	lst.add(new Child1());
    	lst.add(new Child2());
    	lst.add(new Child3());
    	lst.add(new Child4());
    	
    	for(Parent p:lst){    		
    		p.work();
    	}
    	
    	Child1 c1 = (Child1)lst.get(0);
    	c1.relax();
    	
    	Parent parent = getChild("2");
    	parent.work();
    }
    
    public static Parent getChild(String childName){
    	Parent p = null;
    	if(childName.equals("1")){
    		p = new Child1();
    	} else if (childName.equals("2")){
    		p = new Child2();
    	} .......
    	
    	return p;
    }
}
Output
working
working
working
working
relaxing 1
working