DaisukeのITメモ

一人前になる為に。

オブジェクト指向の三大要素について

目次

概要

社会人1年目のJava研修にて概念のWhat(何をする事なのか)は理解できたが、Why(何故やるのか、そのウマミ)までは腑に落ちなかったオブジェクト指向三大要素。
今更だが、Whyも基本的なレベルまで理解した気がするため、以下に纏める。
(成長させて頂けるので、マサカリ大歓迎です。)

オブジェクト指向の三大要素

カプセル化(隠蔽)

What(何をする事なのか)

  • クラスのメンバー(フィールドとメソッド)を宣言する際に下記アクセス修飾子(Javaの例)を付与する事で、他クラスからそのメンバーへのアクセス(取得,更新,実行)権限を制限する事。
    • private
    • protected
    • public
  • アクセスを制限したフィールドの取得と更新は、それ専用のメソッド(getter,setter)を使用して行う。

Why(何故やるのか、そのウマミ)

クラス提供者目線

外部から勝手にアクセスされたくないメンバーへのアクセスを遮断できる。

クラス利用者目線

利用して良いメンバーだけ明示的に公開されている事で、利用するクラスの仕様を気にする事なく利用しやすくなる。

継承

What(何をする事なのか)

  • クラス宣言時に既存クラスを継承(Javaならextends)し、既存クラスと親子関係を持つ事により、大きく下記2点の効果を得られる。
    • 親クラスが持っているメンバー(フィールドとメソッド)をそのまま引き継げる。
      • 子クラスのソースコード上には親クラスのメンバーの記述は無いため目には見えないが、ちゃんと引き継がれている。
    • クラスをグループ化する事ができる。

Why(何故やるのか、そのウマミ)

親クラス提供者目線

子クラスの仕様(メソッド名など)を統一させる事ができる。

子クラス作成者目線

  • 既存クラスと似ているが一部内容が違うというクラスを作成する際、継承を利用する事で下記 を実現できる。
    • ソースコード短縮による可読性向上。
      • 継承を利用しない場合は、親クラスと同ソースコードを子クラスに再記述する事になってしまう。
      • 一方で、継承で親クラスのメンバーを引き継ぐ事は、親子クラスが密結合になるため、デメリットであるという考え方も存在する。
    • メンテナンス性向上。
      • 複数箇所に同ソースコードが記述されていると、メンテナンスのコスト,改修ミスリスクが高くなってしまう。

ポリモーフィズム多態性

What(何をする事なのか)

同一の親クラス(もしくはインターフェース)を持つ複数クラスを、親クラス(もしくはインターフェース)型の変数に代入する事で、一纏めに扱えるようにする事。

Why(何故やるのか、そのウマミ)

クラス提供者目線

複数クラスの仕様(メソッド名など)を統一させる事ができる。

クラス利用者目線

  • 同一の親クラス(もしくはインターフェース)を持つ複数クラスに対して一度のメソッド呼び出しで同時に命令を下せるため、下記を実現できる。
    • ソースコード短縮による可読性向上。
      • 複数クラスをバラバラに扱うと、クラス数の回数だけメソッド呼び出しの記述を行う必要が有る。
    • メンテナンス性向上。
      • メソッドを呼び出す際、メソッドを保有しているのが誰(どのクラス)なのかを気にせず利用する事ができる。

具体例(ソースコード

abstract class Mammal{
    abstract void naku();
}


// Mammalクラスを継承。
class Dog extends Mammal{
    void naku(){
        System.out.println("ワン!");
    }
}


// Mammalクラスを継承。
class Cat extends Mammal{
    void naku(){
        System.out.println("ニャオ!");
    }
}


// ポリモーフィズムを利用した記述のMainクラス。
class Main{
    public static void main(String args[]){
        Mammal[] mammals = new Mammal[2];

        Mammal dog = new Dog();
        Mammal cat = new Cat();

        mammals[0] = dog;
        mammals[1] = cat;

        // メソッド呼び出し処理が下記の様に複数箇所存在する場合に、仕様変更でCatクラスがBirdクラスに変わったとしても、Catクラスのインスタンス化部分だけ改修すれば良い。
        // つまり、メソッド呼び出し部分は改修不要。(メソッドを保有してるクラスが誰かなんて気にしなくて良い。)
        for(Mammal mammal: mammals) {
            mammal.naku();
        } 

        for(Mammal mammal: mammals) {
            mammal.naku();
        } 

        for(Mammal mammal: mammals) {
            mammal.naku();
        } 
    }
}


// ポリモーフィズムを利用しない記述のMainクラス。
class Main2{
    public static void main(String args[]){

        Dog dog = new Dog();
        Cat cat = new Cat();

        // メソッド呼び出し処理が下記の様に複数箇所存在する場合に、仕様変更でCatクラスがBirdクラスに変わってしまうと、Catクラスのインスタンス化部分だけの改修では不充分。
        // 全てのメソッド呼び出し箇所も改修する必要が有る。(メソッドを保有してるクラスが誰かを気にしなくてはならない。)
        dog.naku();
        cat.naku();

        dog.naku();
        cat.naku();

        dog.naku();
        cat.naku();
    }
}

所感

  • 親クラス継承インターフェース実装の両方が存在するウマミが分からない。
    • 1つのクラスは1つの親クラスしか継承できないのに対し、インターフェースは何個でも実装できるため、インターフェースだけで事足りるのでは?
    • インターフェースは抽象メソッドしか定義できないが、親クラスは普通のメソッドも定義できるという違いがウマミ?
  • この程度の記事を書くのに1.5hもかかってしまった。もう少し文章Outputの速度を上げる必要が有る。

/* -----codeの行番号----- */