既存クラスの性質を引き継いで新しいクラスを作る仕組み。
継承とは、すでにあるクラス(=データと処理をまとめた型の設計図)の性質を引き継いで、新しいクラスを作る仕組みのことです。引き継がれる側を親クラス(スーパークラス)、引き継ぐ側を子クラス(サブクラス)と呼びます。
身近な例で考えると、料理のレシピに似ています。「基本のカレー」というレシピ(親)があり、それをベースに「辛口カレー」や「シーフードカレー」(子)を作ると考えてください。基本の手順はそのまま受け継ぎ、足りない部分だけ書き足せばよいので、毎回ゼロから書き直す必要がありません。
上のツールで▶ボタンを押すと、親クラス Animal を子クラス Dog が継承し、属性や操作を自動で引き継いだうえで独自の機能を足していく流れを順番に確認できます。
継承では、クラスどうしが「〜は〜の一種である(is-a 関係)」でつながります。Dog is a Animal(犬は動物の一種)と読めるとき、Animal を親、Dog を子にするのが自然です。
親子関係には次のような特徴があります。
・引き継ぎ:子は親の属性(name・age)と操作(eat()・sleep())を自動で受け継ぐ
・追加:子は自分だけの属性(breed)や操作(bark())を足せる
・共有:1つの親から Dog・Cat・Bird など複数の子を作れる
上に行くほど抽象的(おおまかな共通の性質)、下に行くほど具体的(個別の特徴を持つ)になります。組織図で上司が共通の方針を決め、部下が個別の仕事を足していくイメージに近いです。
継承は便利な仕組みですが、使いすぎると逆に管理が難しくなることもあります。良い面と注意点の両方を押さえておきましょう。
目安として、「AはBの一種だ」と自然に言えるときだけ継承を使い、そう言えない場合は別の手段(部品として持たせる「委譲」など)を選ぶと、後から困りにくい設計になります。
継承を使う最大の理由は「同じコードを何度も書かなくて済む」からです。たとえば Dog と Cat と Bird というクラスを作るとき、継承なしだと「name(名前)・age(年齢)・eat()(食べる)・sleep()(寝る)」という共通の属性・操作をそれぞれのクラスに全部コピーしなければなりません。
コピーが増えると、後で「eat()の動作を直したい」となったとき、Dog・Cat・Bird の全クラスを1つずつ直す必要が生じます。直し忘れや書き間違いがバグになりやすく、クラスが10個・100個になると手に負えなくなります。
継承を使えば、共通部分を Animal(親)に1度書くだけで Dog も Cat も Bird も自動で使えます。eat()を直したいなら Animal の1か所を変えるだけで全子クラスに反映されます。
・継承なし:共通コードを各クラスにコピー → 修正が大変・バグが混みやすい
・継承あり:親に1度書いて子が引き継ぐ → 修正が1か所で済む・整合性が保ちやすい
継承とカプセル化はセットで使われることが多い仕組みです。継承でクラスを引き継いでも、親クラスが private(=外部非公開)にしたデータは子クラスから直接触ることができません。
上の図を見てください。Animal が private で持つ name や age は、子クラス Dog からも直接アクセスできません。Dog が name を知りたいときは、Animal が公開している窓口 getName() を使う必要があります。
・カプセル化の役割:データを隠して各オブジェクトを安全に保つ
・継承の役割:安全にカプセル化された親クラスを土台として再利用する
つまり、カプセル化で「各オブジェクトの内部を守りながら」、継承で「共通部分を使い回す」という分業になっています。2つ合わさることで、安全かつ無駄のない設計が実現します。