おはようございます。こんにちは。こんばんは。
本日は、オブジェクト指向志向プログラミングの特徴の一つである継承についてです。
継承とは
クラス同士の親子関係を表します。
一般的に子クラスB is a 親クラスAの時に継承を使用します。
public class Child extends Parent {
}
継承のメリット
まず継承のメリットについて説明します。
①親子関係を表すことによってクラス間の役割を可視化できる
システム開発→運用段階に入って時間がたっていくと徐々にコードの管理が難しくなっていきます。継承を用いてクラスの同士の親子関係を可視化することでクラスの役割を明確化し、運用保守フェーズに入ってもソースコード管理がしやすくなります。
②親クラスが抽象クラスであれば、子クラスに実装の詳細を任せることができ、コードの柔軟性を上げることができる
親クラスを抽象クラスにすることで親クラスで実装の骨組みだけ作り、子クラスに実装の詳細を任せるというコード設計が可能になります。
③メソッドの重複を防ぐことによりDRY原則を順守することができる
継承を使用することで、子クラスは親クラスのメソッドを自由に使用することができます。もし継承を使用しない場合は、二つのクラスに同じメソッドを使用しなければなりませんが、継承を使用することでコードの重複を防ぐことができます。
継承のデメリット
続いて継承のデメリットについて説明します。
①クラス同士が密結合となってしまう
最も大きなデメリットです。結合度とは複数のモジュール(ここではクラス)がお互いに依存しあっている度合いのことで、一般的には結合度が低い(クラス同士が依存しあっていない)方が望ましいと言われています。継承を使用すると、結合度が高くなります。
例えば
abstract Animal{
abstract void run();
public void walk(){
System.out.println("尻尾を振りながら歩く");
};
}
public class Cat extends Animal{
@Override
public void cry(){
System.out.println("ニャー");
}
}
public class Dog extends Animal{
@Override
public void cry(){
System.out.println("ワンワン");
}
}
上記のAnimalクラスのwalkメソッドのロジックを変更するとします。この時に子クラスであるCatクラスやDogクラスにも影響が出ます。このように継承は親クラスを変更したときに親クラスを継承している子クラスにも影響が出るためこの点が非常に大きなデメリットと言えます。
②高階層の継承の場合、クラス間の関係がわかりずらくなる。
例えばChildクラスはParentクラスを継承していて、ParentクラスはGrandFatherクラスを継承している場合、運用保守の立場で考えるとクラス間の関係や、メソッドがどこから来ているのかなどわかりずらくなります。
public class Child extends Parent {
}
public class Parent extends GrandFather {
}
public class GrandFather {
}
→3つ以上の親子関係を作ると運用保守が大変です。。
委譲を使おう
本記事の主題です。
上記のようにクラス間の親子関係を表す継承はデメリットが大きいです。
そこで、委譲という仕組みを検討しましょう。
「委譲」とは、権限や権利などを他人に任せて、ゆだねることです。
使用されるクラスA、使用するクラスBとしたときにBに対して「Aを使用してください」と表現するときに委譲という仕組みを使います。
二つのクラスCarクラスとEngineクラスで例を出してみます。
public class Car{
private Engine engine;
public Car(Engine engine){
this.engine = engine;
}
}
Carが使用する側、Engineが使用される側です。使用される側をprivateのフィールドで持ち、コンストラクタで初期化して使用します。
両者を考えたときにエンジンは車の一部分であると言えますね。クラスB has a クラスAの関係が成り立つときに委譲を使用しましょう。委譲で結びついているときは、クラス同士は疎結合であるため一方のクラスの変更が他方に影響しなくなります。継承のデメリットを緩和するのが委譲と言えます。
まとめ
①継承はクラス間の親子関係を表しコードの再利用性を向上させるが、クラス同士が密結合になるというデメリットがあります。
②上記デメリットを解決するために委譲を使ってクラス間の疎結合を実現しましょう。
③継承を使うか委譲を使うかのポイントは、
継承→子クラス is a 親クラスにYesと言えるか?
委譲→クラスB has a クラスA(一方のクラスは他方のクラスの持ち物であるか)にYesと言えるか
で決めましょう。