🐕

Java言語における継承の規則についての個人的まとめ

2022/06/28に公開

目次

  1. Is-a(イズ ア)の関係
  2. 継承できないクラス(一切の継承ができない)
  3. 封印されたクラス(指定したクラスだけが継承を許される)
  4. 継承できないメンバ

Is-a(イズ・ア)の関係

クラスをつくる目的とは同種のオブジェクトの系統を作ることであって少ない手間でサブクラスを作ることではない。
前回の記事であったように(親クラス:Car、子クラス:SportsCarのように)Is-aの関係とは、

子クラスは親クラスから分岐したかどうか

で考える。言い換えると子クラスBは親クラスAの一種である」と言う関係が成り立つと言うこと。
「男」クラスの一種である「イケメン」「おっさん」であったり、「歌手」クラスの「さだまさし」「Aiko」「嵐」といったふうに。

  • サブクラスを作るときはこういったIs-a関係を確認するべき。

継承できないクラス(一切の継承ができない)

  • 多くの標準クラスはシステムの根幹機能に関わるので継承して使えない、なぜ使えないのか?
    原因はfinal修飾子がクラス宣言につけてあるからだ。

final修飾子の効果

  1. クラス宣言時:継承できないクラスになる
  2. メソッド宣言時:オーバーライドできないメソッドになる
  3. 変数宣言時:初期値を変更できないようにする

封印されたクラス(指定したクラスだけが継承を許される)

クラスに修飾子sealedをつけると、指定した名前の子クラスを作れる。
こうすることでクラス階層を設計者完全に理解することができるし、不用意な継承も防止できる。
*sealed = 「封印された」の意

title
public sealed class SakamitiGroup permits Nogizaka46, Hinatazaka46{
  // //
}

的な感じだな。
親クラスではsealed修飾子をつける。キーワードpermitsの後ろにつづけて許可するサブクラス名を列挙する。
また、

title
public final class Nogizaka46 extends SakamitiGroup{
  // //
}
title
public non-sealed class Hinatazaka46 extends SakamitiGroup{
  // //
}

というふうに子クラスでは必ずclassの前にfinal,sealed,non-sealedのどれかをつけて宣言する。
意味は次のようになります。

  • final: このサブクラスは継承できない
  • sealed: このサブクラスは封印されたクラスにする
  • non-sealed: このサブクラスは継承できる

さらに親クラスと子クラスは互いにアクセスできるようになっている必要があるので
同じパッケージ、同じモジュールに入っている必要がある。

継承できないメンバ

privateなメンバは継承されないことは前回の記事で触れたが、コンストラクタとスタティックメンバについては注意が必要。

①コンストラクタ:クラスのメンバではないのでインスタンスを作ってもその中には存在しない。したがって継承されることもない。
②スタティック(static)メンバ:スタティックはそもそもインスタンスに含まれない(プログラムの実行前にメモリ上にコピーされる)ので、インスタンスには含まれない。
というか、継承とは全くの無関係である。
継承されないものをまとめると、以下のようになる。

  • privateな変数は継承されない
  • コンストラクタはメンバではないので継承されない
  • staticメンバはインスタンスの中に含まれないので継承とは無関係である

以上です。参考は「新わかりやすいJava オブジェクト指向徹底解説」

GitHubで編集を提案

Discussion