Java言語を使ってインターフェースのメリットを考える

2021年8月12日木曜日

Engineer

本記事では、Java言語を使ってインターフェースとは何なのか。インターフェースを使うことのメリットを紹介します


アイキャッチ

インターフェース(interface) とは

インターフェースとは、
具体的な処理(実装)を記述せず、関数の型と引数のみを定義した宣言です。

言葉だけだと難しく感じてしまいますね。図で見てみます。

インターフェースと関数呼び出しの比較図

上図は、
通常の関数呼び出しと、Interfaceを利用した呼び出しを図に示したものです。

ここで、Interface Bに注目してみます。
このInterface Bは、Class Bが提供する関数を定義しています。
そして関数の実装そのものはClass Bが持っています。

この時、Interface Bは呼び方だけを宣言しており、その中身の処理(実装)は持っていないという点がInterfaceの特徴です。

以下に、Javaのサンプルコードを記載します。

import java.util.*;

public class Main {
    public static void main(String[] args) throws Exception {
        ClassB _instanceB = new ClassB();
        ClassA _instanceA = new ClassA(_instanceB);
        _instanceA.FuncA();
    }
}

// InterfaceBを介してClassBを利用するClassA
class ClassA{
    private InterfaceB _interfaceB;

    public ClassA(InterfaceB ins){
        this._interfaceB = ins;
    }

    public void FuncA(){
        _interfaceB.FuncB();
    }
}

// ClassBの呼び出し方(FuncB)のみを宣言するInterfaceB
interface InterfaceB {
    public void FuncB();
}

// InterfaceBの実装を提供するClassB
class ClassB implements InterfaceB{
    public void FuncB(){
    	// FuncBの実装
        System.out.println("->FuncB");
    }
}

上記のコードを見ると明確ですが、InterfaceBでは関数の宣言のみで、その中身の実装はClassBが行っていることがお分かりいただけるかと思います。

インターフェースのメリット

ここまででインターフェースとは使い方を宣言しており処理の実装は持っていないというイメージを掴んでいただけたかと思います。では、このインターフェースが何のために存在し、どのような嬉しいことがあるのでしょうか?

メリット1: 責務の明確化

一つ目のメリットとして、責務の明確化があります。
Interfaceを定義することによって、Interfaceに実装を提供するクラスが何をすべきかが明確になります。
また、外部のモジュールによる機能の呼び出し方が明確になります。

実際の開発現場を考えてみます。
先ほどの図のClass AをチームAが、ClassBをチームBが開発することを想定します。

この時、チームAは、チームBが何を開発するのか、
その開発範囲をInterfaceBを見れば確認することが可能です。

チームAは、チームBの成果物であるClass Bを詳細に確認する必要がありません。
これは、InterfaceBがあることにより、Class Bが提供する機能、言い換えれば、チームBの開発担当範囲が見やすくなることに起因します。

Interfaceが定義されていないときClass Bを見渡す必要があるためチーム間のコミュニケーションが別途必要になり煩雑さの基となります

インターフェースが実装を隠蔽することを表す図


メリット2: 変更の影響範囲の極小化

Class Aから見てClass Bの実装はInterface Bによって隠蔽されています。
このことは、Class Bの実装内容が変更されても、Interface Bが変更されない限りClass Aにその影響が及ばないことを意味しています。

ソフトウェアの開発において、いかに楽にコードを修正するか(変更容易性)は、
重要なポイントです。

Interface定義することによって、コード修正の影響範囲を明確にします。

インターフェースが変更の影響を局所化することを表す図

メリット3: テストの容易化

Class AはInterface Bを呼び出すとき、必ずしもClass Bが呼び出される必要はありません。
Interfaceに紐づくインスタンスを切り替えることによって、呼び出すクラスを容易に切り替えます。

図を使ってこの意味を見ていきます。下記のようにClass B2を定義します。

インターフェースによって実装を切り替えることができることを表す図


またこの時のソースコードのサンプルを以下に記載します
import java.util.*;

public class Main {
    public static void main(String[] args) throws Exception {
        ClassB _instanceB = new ClassB();
        ClassB2 _instanceB2 = new ClassB2();

        // Interfaceに提供するInstanceを切り替える
        //ClassA _instanceA = new ClassA(_instanceB);
        ClassA _instanceA = new ClassA(_instanceB2);
        _instanceA.FuncA();
    }
}

// Interfaceを介してClassを利用するClass
class ClassA{
    private InterfaceB _interfaceB;
    public ClassA(InterfaceB ins){
        this._interfaceB = ins;
    }

    public void FuncA(){
        _interfaceB.FuncB();
    }
}

// Classの呼び出し方(Func)のみを宣言するInterface
interface InterfaceB {
    public void FuncB();
}

// InterfaceBの実装を提供するClassB
class ClassB implements InterfaceB{
    public void FuncB(){
        System.out.println("->FuncB");
    }
}

// InterfaceBの実装を提供するClassB
class ClassB2 implements InterfaceB{
    public void FuncB(){
        System.out.println("->FuncB Mock");
    }
}

注目頂きたいのはClassAとInterfaceBには一切変更することなく
InterfaceBのクラスがClassBからClassB2に切り替えられている点です。

MainクラスからInterfaceBの実装が供給されているため、
ClassAはInterfaceBの実装を意識する必要がなくなっています。

このことによって、ClassBが完成するまでの間にテスト用のMockクラスClassB2を使うことが可能となり、テストが容易になります。

まとめ

インターフェースの定義とメリットを紹介させて頂きました。

なかなか定義だけ理解してもその使いどころなどは開発の経験を積んでいかないとピンと来ないところも多いと思います。
本記事を見ていただいて少しでも理解が進んだのであれば幸いです。

AIで副業ならココから!

まずは無料会員登録

プロフィール

メーカーで研究開発を行う現役エンジニア
組み込み機器開発や機会学習モデル開発に従事しています

本ブログでは最新AI技術を中心にソースコード付きでご紹介します


Twitter

カテゴリ

このブログを検索

ブログ アーカイブ

TeDokology