スーパークラスとサブクラスについて、最低限覚えておきたいまとめました。
コード内の ... は、以下に続くものが省略されているのだとお考え下さい。
スーパークラスとサブクラス
下記のコードを例に見ていきます。
inheritance.java
class NamedRectangle extends Rectangle {
...
}
- Rectangle はスーパークラス
- NamedRectangle はサブクラス
- サブクラスは一つのスーパークラスしか持てない
- 全てのクラスは Object クラスのサブクラスである
- final クラスはサブクラスを作れない
継承
inheritance.java
class Rectangle {
int width;
int height;
...
void setSize(int width, int height) {
...
}
}
class NamedRectangle extends Rectangle {
...
}
- サブクラスはスーパークラスのフィールドとメソッドを受け継ぐ
- NamedRectangle では width と height が宣言されていないが、どちらも保持している
- NamedRectangle でも setSize() を呼び出すことが出来る
コンストラクタは継承されない
- スーパークラスのコンストラクタが呼び出せてしまうと、サブクラスで新たに宣言されたフィールドが初期化されない可能性が出てしまうため禁止されている
- 一方でスーパークラスで宣言されているフィールドに関しては、サブクラスでもスーパークラスの引数なしコンストラクタが自動的に挿入されるため、初期化式をサブクラスに記述する必要はない
- super() を使えばスーパークラスのコンストラクタを明示的に呼び出せる
- this() を使えばサブクラスのコンストラクタを明示的に呼び出せる
アクセス制御
- private のフィールドやメソッドはサブクラスに継承されない
- 基本的にフィールドは private にし、ゲッターセッターを書いて情報隠蔽することが推奨される
オーバーライド
inheritance.java
class Rectangle {
...
void setSize(int width, int height) {
...
}
}
class NamedRectangle extends Rectangle {
...
@Override
void setSize(int width, int height) {
...
}
}
- サブクラスで、スーパークラスと同名及び引数列の数が等しいメソッドを宣言すると、そのメソッドを書き換えて宣言することができる
- @Override の記述は無くてもコンパイルは通るが、可読性の観点から常に記述されることが通例となっている
- final メソッドはオーバーライドできない
多態性
inheritance.java
class Rectangle {
...
}
class NamedRectangle extends Rectangle {
...
}
- 下記のように、サブクラスのインスタンスはスーパークラスのインスタンスとみなすことができる
inheritance.java
NamedRectangle nr = new NamedRectangle("Steve Aoki");
Rectangle r = nr;
- しかし、r からはサブクラスで宣言されたフィールドを参照することはできない
- メソッドを呼び出す際は、もしそれがサブクラスでオーバーライドされていたら、サブクラスのメソッドが呼び出される
- r に対してキャストを使えばスーパークラスのメソッド呼び出すことができる
抽象クラス
inheritance.java
abstract class Player {
public abstract void play();
public void loop(int n) {
for (int i = 0; i < n; i++) {
play();
}
}
}
- 抽象クラスとは、メソッドの名前と引数の型が決まっていて、実装がない抽象メソッドを含んだクラスのこと
- 自ら実装はしないが、サブクラスに対し、どのような実装をするかを強制する
- Byte, Integer などのクラスのスーパークラスである Number クラスが代表例