クラスの継承、オーバーライド、型変換についての忘備録

Javaを始めた当初からよく分かってない問題があり、根本的な解決はしてないものの動作の確認はしたので記録しておく。

このようなクラスを継承した

class SuperClass {
	String superStr;
	SuperClass(){
		System.out.println("SuperClassの引数なしコンストラクタが実行されました");
	}
	SuperClass(String str){
		System.out.println("SuperClassの引数ありコンストラクタコンストラクタが実行されました");
		this.superStr = str;
	}
	public void overRideMethod() {
		System.out.println("SuperClass側のメソッドが実行されました");
	}
	public void superMethod() {
		System.out.println("SuperClassにしか定義されていないメソッドです");
	}
}

こんなクラスがあったとして、

class SubClass extends SuperClass{
	String subStr;
	SubClass(){
		// super()が暗黙的に実行される
		System.out.println("SubClassの引数なしコンストラクタが実行されました");
	}
	SubClass(String str, int num){
		// super()が暗黙的に実行される
		System.out.println("SubClassの引数ありコンストラクタが実行されました");
		this.subStr = str;
	}
	// SuperClassのメソッドをオーバーライド
	public void overRideMethod() {
		System.out.println("SubClass側のメソッドが実行されました");
	}
	public void subMethod() {
		System.out.println("SubClassにしか定義されていないメソッドです");
	}
}

なお各クラスのフィールドのカプセル化は面倒なので省いた。
その上で以下のことを調べた。

  • SuperClass型のSubClassオブジェクトがアクセスできるメンバはどれか。及び両クラスに定義されているoverRideMethod()のどちらが実行されるか。
  • SubClass型のSubClassオブジェクトをSuperClass型に変換した後、①と同じテストをした場合得られる結果。

結果はこう。

  • SuperClass型のSubClassオブジェクトがアクセスできるメンバはどれか。及び両クラスに定義されているoverRideMethod()のどちらが実行されるか。
SuperClass sp2 = new SubClass();
sp2.overRideMethod(); // 結果:SubClass側のメソッドが実行されました
sp2.superMethod();
// sp2.subMethod(); コンパイルエラー
sp2.superStr = "『SuperClassのフィールドです』";
// sp2.subStr = "『SubClassのフィールドです』"; コンパイルエラー
  • SubClass型のSubClassオブジェクトをSuperClass型に変換した後、①と同じテストをした場合得られる結果。
SubClass sb2 = new SubClass();
SuperClass sbToSp = (SuperClass)sb2;
sbToSp.overRideMethod();// 結果:SubClass側のメソッドが実行されました
sbToSp.superMethod();
// sbToSp.subMethod(); コンパイルエラー
sbToSp.superStr = "『SuperClassのフィールドです』";
// sbToSp.subStr = "『SuperClassのフィールドです』"; コンパイルエラー

結果を見ると、アクセスできるメンバは型に依存して、overRideMethod()は実際に動作するオブジェクト自身に左右されるっぽい。
なんでそうなるかは頭わるわるなので保留にします。