Java の継承を使うべき場面と使わないほうがよい場面を初心者向けに解説!
新人
「Javaの継承って、どんなときに使うと便利なんですか?」
先輩
「いい質問だね!継承は使い方を間違えると逆にややこしくなるから、使う場面をしっかり見極めるのが大事だよ。」
新人
「なるほど…。じゃあ、使うべきときってどんなときですか?」
先輩
「それじゃあ今回は、Javaで継承を使うべき場面とその理由を具体例を交えて解説していこう!」
1. Javaの継承とは?(やさしく復習)
Javaの継承とは、あるクラス(親クラス)の機能を、別のクラス(子クラス)が引き継ぐ仕組みです。これにより、共通の処理を親クラスにまとめておき、子クラスで再利用することができます。
たとえば、動物を表すAnimalクラスがあり、犬や猫などの具体的な動物クラスがそれを継承することで、共通の動作(例:眠る)を共有できます。
継承を使うことで、コードの重複を減らし、保守性を高めることができます。
2. 継承のメリットとは?使うと何が便利なのか
Javaの継承を使うことで、以下のようなメリットがあります。
- コードの再利用性向上:共通の処理を親クラスにまとめることで、子クラスで同じコードを書く必要がなくなります。
- 保守性の向上:共通の処理を一箇所にまとめることで、修正が必要な場合でも親クラスを変更するだけで済みます。
- 拡張性の確保:既存のクラスを拡張して新しい機能を追加できるため、柔軟なプログラム設計が可能になります。
これらのメリットにより、Javaの継承は、共通処理の再利用やコードの整理に役立ちます。
3. Javaの継承を使うべき場面とは?(具体例で解説)
Javaの継承を使うべきタイミングは、クラスどうしに「〜は〜である」という関係がはっきりしているときです。たとえば、「トラックは車である」「柴犬は犬である」といった場面です。
このような関係があるとき、親クラスに共通の処理をまとめておくことで、子クラスはそれを再利用でき、Javaでのコードの重複を避けることができます。
以下のようなコードを見てみましょう。
public class Vehicle {
void move() {
System.out.println("走行します。");
}
}
public class Truck extends Vehicle {
void load() {
System.out.println("荷物を積みます。");
}
}
public class Main {
public static void main(String[] args) {
Truck t = new Truck();
t.move(); // Vehicleのメソッド
t.load(); // Truck自身のメソッド
}
}
走行します。
荷物を積みます。
TruckはVehicleの機能を引き継いでいるため、共通の処理をすべて再利用できます。
4. クラスの共通点があるときに継承は効果的
たとえば、DogとCatという2つのクラスがあり、それぞれ眠るという動作を持っていたとします。
このとき、Animalという親クラスに共通のsleep()メソッドを定義しておくことで、それぞれの子クラスで同じ処理を書く必要がなくなります。
public class Animal {
void sleep() {
System.out.println("眠ります。");
}
}
public class Dog extends Animal {
void bark() {
System.out.println("ワンワン!");
}
}
public class Cat extends Animal {
void meow() {
System.out.println("ニャー!");
}
}
このようにクラスに共通点があるときは、Javaの継承を使うことでクラスの構造を整理しやすくなります。
5. 同じ処理を何度も書きたくないときの活用法
たとえば、ログイン画面とメイン画面のどちらにも「ヘッダーを表示する」処理が必要な場合、それを毎回書くのは非効率です。
そのような場合は、親クラスに共通の処理をまとめておき、子クラスで再利用することで、Javaのコードを簡潔に保つことができます。
public class BaseScreen {
void showHeader() {
System.out.println("=== ヘッダー表示 ===");
}
}
public class LoginScreen extends BaseScreen {
void showContent() {
System.out.println("ログイン画面です。");
}
}
public class MainScreen extends BaseScreen {
void showContent() {
System.out.println("メイン画面です。");
}
}
public class Main {
public static void main(String[] args) {
LoginScreen login = new LoginScreen();
login.showHeader();
login.showContent();
MainScreen main = new MainScreen();
main.showHeader();
main.showContent();
}
}
=== ヘッダー表示 ===
ログイン画面です。
=== ヘッダー表示 ===
メイン画面です。
このように、同じ処理を複数の場所で使いたいときに、Javaの継承は非常に便利です。
6. 継承を使わないほうがよい場面とは?
Javaの継承は便利な仕組みですが、どんなときでも使えばよいというわけではありません。たとえば「〜は〜である」という関係が成り立たない場合、無理に継承を使うと逆にコードがわかりにくくなってしまいます。
たとえば、PrinterクラスとScannerクラスがあったとしても、「スキャナーはプリンターである」とは言えません。このような場合には、継承ではなく、別の方法(コンポジションなど)を使うほうが自然です。
また、機能がまったく違うのに無理に共通の親クラスにしてしまうと、子クラスの中で使わないメソッドが出てきたりして、コードの見通しが悪くなります。
7. クラスの関係が複雑になるデメリット
Javaの継承を重ねすぎると、コード全体の構造が複雑になりがちです。たとえば、親クラスがさらに親クラスを持ち、そのまた親があると、どこにどの処理があるのかが見えにくくなってしまいます。
これは、ちょうど家庭の家系図が複雑になりすぎて、「この親戚は誰の子なのか?」と混乱するような状態に似ています。
コードの修正やバグの調査のときに、親クラスに影響される子クラスが多すぎると、「この変更がどこまで影響するのか」を把握するのが難しくなってしまいます。
そのため、Javaの継承は2〜3段階くらいまでに抑えるのが初心者にはおすすめです。
8. 初心者が継承を使うときに気をつけるポイント
Javaの継承はとても便利ですが、初心者が使うときには次のポイントに注意しましょう。
- 本当に「〜は〜である」関係があるかをよく考えること
- 共通の処理だけを親クラスにまとめて、無理に似ていない機能を入れないこと
- 継承の段階はできるだけ浅くして、構造がわかりやすいようにすること
たとえば、次のように親クラスに共通の処理だけを置いて、子クラスではそれぞれの動きを書くという形が理想です。
public class MessageSender {
void sendHeader() {
System.out.println("--- メッセージ開始 ---");
}
}
public class EmailSender extends MessageSender {
void sendMessage() {
sendHeader();
System.out.println("メールを送信します。");
}
}
public class SmsSender extends MessageSender {
void sendMessage() {
sendHeader();
System.out.println("SMSを送信します。");
}
}
--- メッセージ開始 ---
メールを送信します。
--- メッセージ開始 ---
SMSを送信します。
このように、共通する処理は親クラスに、個別の処理は子クラスに書くことで、Javaの継承を使って効率的で見やすいコードになります。
初心者向けのJava開発では、まずは「共通の処理がある」「〜は〜である」と自然に思える場面だけで使うことから始めてみましょう。