インターフェイス

インターフェイスとは、実装の無いpublicな抽象メソッドで構成されたものです。

インターフェイスは、publicメソッドを定義しますが、機能を実装しません。
ただし、フィールド(固定値のみ)、メソッド名、メソッドの引数と型、戻り値は定義します。

インターフェイスには、3つの役割を持ちます。

  1. 公開するクラスの仕様の確定。
    大規模システムにおいて複数の開発チームで作業し、サブシステム間で連携をするWebサービスを開発する事が多々あります。
    呼び出し側は、呼び出すサービスの実装は知らなくても、メソッド名、メソッドの引数と型、戻り値、例外と仕様のみ
    理解しておけば良いのです。これにより、呼出し側は、協業する際にインターフェイスで決めた仕様で連結部分の
    プログラムを受け側のシステムができる前に実装をできます。
  2. JavaAPIの特化した機能の定義。
    Javaには、並列処理を実現するクラスにThreadクラスがあります。
    さらにThreadを利用するには、Rnnableインターフェイスをimplementsしたクラスを作成して、
    Threadクラスのデフォルトコンストラクタに引き渡す必要があります。
    このようにJava言語内でもいくつかのインターフェイスが提供されていますが、
    それぞれ何かしら特化した機能を利用するために作成されたものです。
  3. 複数の機能を明示化。
    Javaプログラムでは、親クラスを1つ以上設定する多重継承を認めていません。
    その変わり、interafaceを複数implementsすることは可能です。
    2.特化した機能の公開仕様を1つ以上付与することができる事で、 implementsしたクラスがどのようのな機能(振る舞い)があるかinterfaceから判断できます。

1.のケースで作成するクラスはインターフェイスと明確に区別するために接尾語に「Impl」を付与します。
これは、「implements(実装)」の略です。

インターフェイスの構文

interface
public class 利用する子クラス implementsインターフェイス1,インターフェイス2

インターフェイスのサンプル1

Web3階層システムにおいてインターフェイスを利用する事例です。1.公開するクラスの仕様の確定のサンプルになります。

Web3階層システムにおいて、エンジニアは、プレゼンテーション(主に画面)とビジネスロジック(Service)とデータ(Dao)で分業します。
プレゼンテーション層を担当するエンジニアは、ビジネスロジック以下の詳細は深く知る必要はありません。
知っておくべきことは、ビジネスロジック層のサービスクラスがどのような機能があるかです。
そして、その機能の概要と入力引数、戻り値の仕様を理解していおけばよいのです。

対して、ビジネスロジックとデータ層を作成するエンジニアは、サービスの機能の概要と入力引数、戻り値を設計書に従い公開します。
インターフェイスは、公開した仕様なので一度決めた引数、メソッド名、戻り値を勝手に変更してはいけません。
変更する場合には、チームにアナウンスしてインターフェイスの変更を相談して確定します。

このようにインターフェイスは、実装(implements)するクラスにインターフェイスに定義したメソッドの実装を強制します。

ECサイトで買い物カゴに商品を入れて購入手続きを実行することを想像して下さい。

ECサイトでは、利用者に多くの商品を購買して頂くために買い物カゴ機能が存在します。
買い物カゴに入れた商品は、買い物カゴに入れた日に購入しなくても、データベースに保存されます。
そして、給料日後に実際に購入手続きだけをした場合に必ず次のチェック(ビジネスロジック)が実行されます。
買い物カゴに入れた時の商品の値段と現在の商品の値段が異なったり、在庫有無をチェックしたりと多くのチェック処理を実施します。

上記UMLのように、OrderServiceインターフェイスがcheckOrderメソッドを定義しているので、
OrderServiceインターフェイス実装したクラスOrderSeviceImplクラスは、checkOrderメソッドを実装しているのです。

OrderServcie.java
/**
 * Copyright 2017 yourcompany.
 * 本ソースファイルの著作権は株式会社yourcompanyに所属します。
 * 株式会社yourcompanyの許可なくして、本ソースファイルの
 * 配布、改修、コピー、利用を禁止します。
 * 会社名               :株式会社yourcompany
 * 組織名               :システム開発部
 * プロジェクトコード   :education
 * バージョン           :1.0
 * 最終更新日時         :2017/03/07 20:00
 */
package jp.co.yourcompany.education.order.service;

import java.util.List;

import jp.co.yourcompany.education.order.dto.OrderCartItem;
import jp.co.yourcompany.education.order.dto.OrderCheckResult;

/**
 * インターフェイスを理解するための
 * サンプルインターフェイス
 * @author raita.kuwabara
 *
 */
public interface OrderService {

    /**
     * このサービスのサブシステムコード
     */
    public static final String SUBSYSTEM_CODE = "order";


    /**
     * カートに指定された商品の在庫数や購入価格と現在価格の差異のチェックなど
     * 購入者に警告メッセージが必要な商品の警告を返すサービス
     * @param itemList 買い物カゴの商品リスト
     * @return 警告リスト サイズが0の場合には、警告なし
     */
    public List<OrderCheckResult> checkOrder( List<OrderCartItem> itemList);

}
                
OrderServcieImpl.java抜粋
//コメント割愛
package jp.co.yourcompany.education.order.service;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;

import jp.co.yourcompany.education.order.dto.OrderCartItem;
import jp.co.yourcompany.education.order.dto.OrderCheckResult;

/**
 * 注文サービス
 * @author raita.kuwabara
 */
public class OrderServiceImpl implements OrderService {

    /**
     * 買い物カゴの商品をチェックし、チェックした結果を返す。
     * @param itemList カート商品のリスト
     * @return resultList 商品チェック結果 配列数0の場合には、警告なし。
     */

    @Override
    public List<OrderCheckResult> checkOrder(List<OrderCartItem> itemList) {
        List<OrderCheckResult> resultList = new ArrayList<OrderCheckResult>();
        for( OrderCartItem cartItem : itemList ) {
            OrderCheckResult checkResult = null;
            checkResult = checkDifferencePrice( cartItem );
            if( checkResult != null){
                resultList.add( checkResult );
            }
            checkResult = checkStock( cartItem );
            if( checkResult != null){
                resultList.add( checkResult );
            }
        }

        return resultList;
    }
				

implementsした子クラスがメソッドを実装する場合には、@Overrideアノテーションをメソッド定義前行に宣言します。

@Overrideアノテーション
@Override
public 型 継承した親クラスのメソッド名 hoge(){ //実際の処理 }

多様性でも詳しく説明いたします。

インターフェイスのサンプル2

次のサンプルは、「2.JavaAPIの特化した機能の定義」「3.複数の機能を明示化」の例を説明します。

上記UMLでは、買い物カゴの商品情報を保存するDtoオブジェクトです。

OrderクラスのimplementsをみるとClonableとSerializableを利用しています。

Clonableインターフェイスはオブジェクトのコピー機能に特化したインターフェイスです。
Clonableインターフェイスをimplementsしたクラスはclone()メソッドに
オブジェクトのコピー内容を実装することで、オブジェクトのコピー機能が実現できます。

Serializableインターフェイスはオブジェクトを出力ストリームに書き出せる機能です。(シリアライズ)
Serializableは、シリアライズしたいDtoオブジェクトにimplmentsするだけでそのオブジェクトがシリアライズできるオブジェクトになります。

以上より、Orderクラスは、「コピー機能」「シリアライズ機能」を持つDtoとなります。

Order.java抜粋
import java.io.Serializable;
public class Order implements Cloneable ,Serializable {

    /**
     * オブジェクトのコピーを取得する。
     */
    @Override
    public Order clone() {
        Order copyObj = null;
        try {
            copyObj = ( Order ) super.clone();
            //ディープコピー オブジェクト型は明示しないと同じインスタンスを指してしまう。
            copyObj.setOrderDate( new java.util.Date( this.getOrderDate().getTime() ) );
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return copyObj;
    }
    //他メソッド割愛
}
				
OrderCartItem.java抜粋
public class OrderCartItem extends Order {
    /**
     * オブジェクトのコピー
     */
    @Override
    public OrderCartItem clone(){
        OrderCartItem copyObj = null;
        copyObj = ( OrderCartItem ) super.clone();
        copyObj.setDateInCart( new java.util.Date ( this.getDateInCart().getTime() ) );
        return copyObj;
    //他メソッド割愛
    }
}
					

インターフェイスは、理屈で覚えるのではなく多くの一流ソースを見て、多くのソースを記述することで使いどころが身に付きます。

JavaAPIには、各種機能を実現させるためのインターフェイスが多く提供されています。
実装するときにJavaAPIを確認して、これはinterfaceだからimplementsするときに公開されたメソッドを実装しなくてはならないなと
それだけを覚えていれば良いだけです。細かい機能の実装はJavaAPIや本サイトなどの技術サイトで確認すれば良いのです。

サンプルのダウンロードと実行方法

  • java_sample10.zipファイルを「c:¥download¥java¥samples¥」に保存して下さい。
  • java_sample10.zipファイルを「c:¥projects」配下に展開して下さい。
  • コマンドプロンプトを起動して、「interfacejar.bat」を実行して下さい。
  • javac,jarが実行されてdeployディレクトリに「education-main.jar」が作成されます。
  • コマンドプロンプトから「interface1.bat」を実行して下さい。
  • jp.co.yourcompany.educatoin.order.dto.OrderCartItem.javaのソースファイルの中身と実行結果を確認して下さい。
  • コマンドプロンプトから「interface2.bat」を実行して下さい。
  • jp.co.yourcompany.educatoin.order.servcie.OrderSeviceImpl.javaのソースファイルの中身と実行結果を確認して下さい。
  • ※.サンプルソースファイルを改修した場合には、毎回「interface1.bat」でコンパイルとjarの再作成をして下さい。
  • Linux,Unix,iOSの方はバッチファイルはお手数ですが作成して下さい。改行コードが「CRLF」の点ご留意ください。