MYAO's WEBSITE

2017-01-11

サブクラスのインスタンスをスーパークラスの変数に代入した時の話

タイトルの言い方でええのんかわからんけど、Javaであるクラスを継承したクラスを親クラスの型を持つ? 変数に代入した時の話。

// Sub.java  
public class Sub extends Super{  
  /**  
     Print "piyo" to the standard output.  
  */  
  @Override  
  public void piyo(){  
    System.out.println("piyo");  
  }  
  /**  
     Print "FUGA" to the standard output.  
     Super class dosen't hava this method.  
  */  
  public void fuga(){  
    System.out.println("FUGA");  
  }  
}  
 
//Super.java  
public class Super {  
  /**  
     Print "HOGE" to the standard output.  
  */  
  public void hoge(){  
    System.out.println("HOGE");  
  }  
  /**  
     Print "PIYO" to the standard output.  
  */  
  public void piyo(){  
    System.out.println("PIYO");  
  }    
}  
 
// SubclassTest.java  
public class SubclassTest {  
    public static void main(String[] args){  
        Super superClass = new Super();  
        Sub subClass = new Sub();  
        Super subSuperClass = new Sub();  
 
        System.out.println("Super:");  
        superClass.hoge();  
        superClass.piyo();  
        System.out.println("Sub(Sub):");  
        subClass.hoge();  
        subClass.piyo();  
        subClass.fuga();  
        System.out.println("Sub(Super):");  
        subSuperClass.hoge();  
        subSuperClass.piyo(); // 変数がSuperクラスでもオーバーライドされる。  
        // subSuperClass.fuga(); // Superクラスがfugaメソッドを持ってないのでエラー。  
        ((Sub)subSuperClass).fuga(); //キャストすればOK。  
        System.out.println(subSuperClass instanceof Sub); //trueと印字される。  
    }  
} 

例によって、シンタックスハイライトしていないのはご勘弁を。で、まあ上のようなことを考えました。コメントのとおりですが。

SuperというクラスをSubというクラスが継承していて、piyoというメソッドをオーバーライドして、Superというクラスにはないfugaというクラスを持っています。hogeはSuperというクラスの中でのみ定義されています。

この時、Subクラスの変数にSubのコンストラクタで作ったインスタンスを代入すると、次のようになりました。

となりますが、Superクラスの変数にSubクラスのコンストラクタで作ったインスタンスを代入すると、次のように変わります。

ってな具合になります。変数の方が型をもってるのかなと思いきや、System.out.println(subSuperClass instanceof Sub)では、trueが返ってきます。理由を推測できないわけでもないですけれども、なんとなくややこしい感じがしたので、メモ代わりに。