こんにちは、ともです。
Javaに限りませんが、オブジェクト指向言語にはアップキャスとダウンキャストが存在します。
JavaSilverの取得を目指して勉強している際にかなり間違えましたので、整理しておこうと思います。
アップキャスト
アップキャストは子クラスの型を親クラスの型へキャストすることです。
class A {}
class B extends A{
public void method() {
System.out.println("methodB");
}
}
public class Main {
public static void main(String[] args) {
B b = new B();
// アップキャスト
A b2a = (A) b;
}
}
アップキャストをすることによって、そのインスタンスでできることが制限されます。
子クラスは
- 親クラスの機能
- 子クラス独自の機能
の2つを持っていますが、親クラスにアップキャストしたことにより
- 親クラスの機能
- (使用不可能)子クラスの機能
では、アップキャストにより親クラスで定義された機能しか利用できなくなる例を見てみましょう。
package try_catch_01;
class A {}
class B extends A{
public void method() {
System.out.println("methodB");
}
}
public class Main {
public static void main(String[] args) {
B b = new B();
b.method();
// アップキャスト
A b2a = (A) b;
b2a.method();//未定義エラー
}
}
Aクラスではmethodは定義されていませんので実行できません。
では、Aクラスにもmethodが定義されていた場合はどうでしょうか。
package try_catch_01;
class A {
public void method() {
System.out.println("methodA");
}
}
class B extends A{
public void method() {
System.out.println("methodB");
}
}
public class Main {
public static void main(String[] args) {
B b = new B();
b.method();
// アップキャスト
A b2a = (A) b;
b2a.method();// "methodB"が表示
}
}
親クラスにもmethodを定義し、b2aから参照したところ、コンソールにはmethodBが表示されます。
つまり、
- アップキャスト後の実態はあくまでサブクラス
- アップキャストにより、アップキャストで定義されたものしか利用できなくなる
この2点を理解することができました。
ダウンキャスト
ダウンキャストは親クラスから子クラスに型を変換することです。
次のようにコードを書いてみました。
class A {}
class B extends A{
public void method() {
System.out.println("methodB");
}
}
public class Main {
public static void main(String[] args) {
A a = new A();
B a2b = (B)a;
a2b.method();
}
}
実行すると次のエラーが出ました。
Exception in thread “main” java.lang.ClassCastException: A cannot be cast to B at Main.main(Main.java:11)
AクラスをBクラスにキャストできません、と怒られてしまいました。
上記のようなダウンキャストはできません。次のようなダウンキャストなら可能です。
// 実態はB(ポリモフィズム)
A a = new B();
// B型に戻す
B a2b = (B)a;
a2b.method();
上記のように、
- 実態がBクラスであるが、型はAクラス
- つまり、変数aは型Bを型Aに暗黙的にアップキャストした状態
- それは、実態はBクラスだが、Aの範囲に使用制限をかけた状態
- 変数aをBクラスに戻し(ダウンキャスト)、アップキャストによる使用制限を解除
ダウンキャストを理解するにはまずアップキャストを理解する必要があることがわかりますね。
// *****ダメな例******//
// Aのインスタンス
A a = new A();
// Aがもつ機能を無理やり拡張はできない
B a2b = (B)a;
// *****OKな例******//
// BのインスタンスをAの機能に制限した状態
A a = new B();
// 制限を解除した。無理やり拡張している訳でない。
B a2b = (B)a;
コードを比較してみました。
アップキャストが制限をかけていることを理解すれば、ダウンキャスは制限を解除していると理解できますね。
まとめ
Javaでのアップキャストとダウンキャストについて理解をまとめました。
アップキャスト・ダウンキャストは他の言語でも出てくるので丁寧に理解していきましょう。