MENU

インターフェース・抽象クラス・ポリモーフィズム

はじめに 

他のカリキュラムの内容と比較すると、 少し異色の章となります。 

情報自体はネットに溢れかえっていますが、Javaを知っている前提の内容が多く書きっぷりがシンプルであるため、具体的なイメージが浮かびづらいです。 
そのため、今までの切り口とは少々異なる角度から説明をしていきます。 
また、この章においては課題提出はありません。 
しかし、知識を深めてもらうために、 内容を読み進めつつ同時に実装してみることを推奨します。 
掘り下げると奥が深い内容になりますので、この章に関しては書き方ももちろんそうですが、 

特に使用時のイメージに重きを置いて学習していきましょう! 

Step1: インタフェース 

まずは英語の意味 
→(AとBとの接点、境界面 

インターフェースの使用例 

例1) UI(ユーザーインターフェース 
→今、眼前にいるPCと、この文章を見せてくれてるディスプレイとか! 

例2)API(Application Programing Interface 

この業界では必ずと言っていいほど耳にするワードになります! 
詳しくは記述しませんが、以下にフリマアプリでのAPIの例をあげますので、イメージを掴んでみてください。 

  • ユーザー: 検索ワード=「○○ブランド」 「ジャケット」 を入力して、 検索ボタンをターーーップ! 
  • アプリ: ユーザーからお願いきた! 検索ワードに合った服を探さなきゃ!でも、そのデータ自体は持ってないから、 APIにお願いして取ってきてもらおう! 
  • API : サーバー側にあるデータベースに、 アプリさんから貰った 「○○ブランド」 「ジャケット」 って情報と一致するデータがあったから渡すね! 
  • アプリ: お! API さっすが! ユーザーに見せてあげなきゃ! 
  • ユーザー: お!これこれ! 探してたやつ! 

上記のユーザーとアプリを繋ぐ架け橋となってくれているものがAPIになります! 
ここでのAPIのお仕事はアプリからのリクエストを受け取って、受け取ったリクエストに合った内容をレスポンスするということになっています! 

ユーザーとアプリの境界に立って、 お仕事してくれていますね(^^) 

Javaにおけるインターフェース 

前置きが長くなりましたが、ここからが本番です! 
一番の特徴は、インターフェースの実装対象への依存度が低く、変更に強いプログラムを構築できるという点です! 
その他、細かな特徴をいくつかあげます。 

  • 処理無しのメソッドを記述したクラス 
  • 実装先のクラスは必ずインタフェースで宣言されているメソッドをオーバーライドし、オーバーライドしたメソッドの実際の処理を記述 
  • 実装先のクラスはインターフェースに制御 (コントロール) される意味合いを含む 
  • 実装先のクラスはインターフェースを複数実装できる 
  • 使用目的を明確にて実装内容を絞らないと、ただのお邪魔虫 

なかなか一回で理解するには難しそうです。 

ですので、以下に、現実世界での具体例を交えた内容でコーディングしていきたいと思います! 

【上記特徴を踏まえた具体例】 

~部下Aさん & 上司Zさんと、 愉快な仲間たちのお話~

1. インターフェース (=Zさんの司令) 
2.1の司令をこなす側のAさん 
3. 毎月訪れる現実世界の出来事 ( ※1,2を使ってみる) 
4.Zさんの司令にも慣れてきたので師範代Bさんの司令もこなしてみる 

サンプル: orderFromZ 

インターフェースを作成する際は、通常のクラス作成とは異なった作成方法を取るため、 大まかな手順となる画面を提示します。 

【当該処理のインタフェースの作成】 

■作成したいフォルダやパッケージなどでメニューを開き、[新規] → [インターフェース] を選択 

■名前(青枠) を入力し、 完了ボタンを押下 

また、必須ではありませんが、「コメントの生成」 にチェックを入れると作成時に開発者に優しい開発補助のコメントを自動挿入してくれますので、 必要な場合はチェックを入れておきましょう。 

■インタフェースに持たせたい機能を実装 

ここからインターフェースにメソッドを実装します。 
インタフェースには、そのインタフェースに持たせたい機能(処理やタスク) に適した内容を記述していきます。 

【OrderFromZ.java】 

必要な機能(処理やタスク) の実装 
インタフェースの内容に適したメソッドを定義していきます。 
今回は必要機能に加えて、あえてお邪魔虫な司令を加えています。 
また、インターフェースのアクセス修飾子には基本的に public を指定します。 
protected などが指定されるとコンパイルエラーとなります。 
(それぞれ適した使用ケースがあるのですが、今回は汎用的な public で実装していきます。)

【インタフェースの実装】 

続いてインターフェースを implements (実装) していきます。 
事前にインターフェースの実装対象となるクラスを作成しておきましょう。 (今回はA.java クラスとします。)

■インターフェースをクラスに実装 

クラス名 implements インターフェース名 のように記述します。 
自動作成された直後の状態では、実装したインターフェースのメソッドがクラスに存在しないことによるコンパイルエラーが表示されますので対応していきます。 

エラーアイコン、または、下線が表示されているインターフェースより解決するのですが、

今回はエラーアイコンより解決していきます。 

■エラーアイコンより、 [エラーアイコンをクリック] → [インターフェース名をインポートしますをクリック] 

(これに関しては、imoprtが済んだ状態であればスキップして構いません。)

■エラーアイコンより、 [エラーアイコンをクリック] [実装されていないメソッドの実行] 
インターフェースに定義されている機能(定義した3つのメソッド)を実装します。 
(画像の右側の小窓に表示されている内容になります。)

以下のように、手書きではなくEclipseにお任せすると、 コメント TODO 部分)を自動生成してくれます。
「メソッドは実装しておいたから、 後は好きなように必要な処理を実装してね!」 という意味になります。

インターフェースの実装も完了したので、ここからはコーディング内容を見ていきましょう。 

【A.java】

【AMain.java】 

【実行結果】 

・インターフェースにより実装したメソッドの処理のみを実装 
 大本の司令(勤務表提出・ 交通費提出 ・ おじゃま虫な司令)は、クラス内で定義した訳ではないため、 
 単純にその中身の処理のみを実装することで司令に対しての挙動を表現できます。 

つまるところ、 

・司令(インターフェースメソッド) が増えれば、司令 (インターフェースメソッド)を新たに実装し処理を記述 
・こなす必要の無い司令となったものに関しては、関連する処理を削除するだけで済む 

という訳です! 
もちろん、インターフェースの司令を自身のクラス内で定義して実装することでもやりたいことは実現できるのですが、 複数人で共同開発をしていく上では修正箇所が増えることは作業効率の低下に直結してしまいますし、修正ミスや修正漏れの危険性も鑑みなくてはなりません。 

更に言えば、その修正範囲の試験も実施する必要が出てきます。 
開発者側の都合ではあるのですが、そういった悩ましい局面を軽減してくれる開発の仕方になります! 

サンプル: OrderFromShihandai 

インターフェースの実装は複数可能というところで、もう一つインターフェースを作成しています。 

■複数のインターフェースを実装 

, (カンマ) 区切りで記述していきます。 

※importが必要な場合はimportしましょう 

【OrderFromShihandai.java】 

【A.java】 

【AMain.java】 

【実行結果(※Newの部分のみ)】 

実装手順は難しくありません。 
ここまで読み進めた上で、 再度 【インターフェースの特徴】 を確認してみましょう! 
ほんのりと理解が深まるかと思います! 

Step2: 抽象クラス 

続いて抽象クラスについて。 
インターフェースと同様にまずは特徴を見ていきましょう! 

  • インタフェースと通常のクラスの中間のようなクラス 
  • 通常のクラスと同様に、フィールドやコンストラクタ、メソッドなどの記述が可能 
  • 【抽象メソッド】 という、 処理無しのメソッドの記述が可能 
  • 「継承」と同様に、複数の抽象クラスは継承不可 
  • 抽象クラス内の abstract が付いたメソッド (抽象メソッド)は、この抽象クラスを継承するクラスでのオーバーライドと中身の処理の実装が必須 
  • 必ずサブクラスのインスタンスを生成して使用する 

はい、、、やはり難しいですね。 

悩むよりまずは具体例を見ていきましょう! 

どんな時に使うか? 

  • 絶対的な決まりごと ルールなどを正確に実施させたい場合 
  • 多重継承させたくない (複数の余計な司令をさせたくない)場合 

使用時のイメージ 

日本には法律というものがありますよね? 
例外はありますが、基本的には決まりごとで、 みんなが通る道です。 
そういったルールを設けています。 

【上記特徴を踏まえた具体例】 ~カリキュラムを進めている方 

1. 抽象クラス(=Javaのカリキュラム研修生クラス)
2.1のJavaのカリキュラム研修生を継承する研修生サブクラス 
3.2の研修生クラスがやることは一体何だ?! (1のメソッドを使って確かめる! ) 

インターフェース同様、 大まかな手順となる画面を提示します。 

■抽象クラス (abstract) の作成 

「abstract」のチェックボックスにチェックを入れて作成します。 
(※もしチェックをし忘れても、コード内で「 abstract」と記述すれば問題ありません。)

作成時は特にエラーは発生しません。

■ 抽象クラス(abstract) の実装 

抽象クラスに持たせたい機能を実装していきます。 

[JavaCurriculumTrainee.java】 

■抽象クラスをクラスへ継承 

抽象クラスに定義されている機能 (定義した1つのメソッド) を継承していきます。 
通常の継承 (extends ) と同様、クラス名 extends 抽象クラス と記述します。 (今回は Trainee クラスを対象とします。)

まずは通常のクラス作成より、 Traineeクラスを作成しましょう。 
その後、作成した抽象クラスを継承させます。 

■エラーアイコンより、 [エラーアイコンをクリック] → [実装されていないメソッドの実行] 

■エラーアイコンより、 [エラーアイコンをクリック]→[コンストラクター “Trainee (String) を追加します] 

抽象クラスで実装したコンストラクターも実装していきます。 

またまたEclipseへお任せします。 

クラスへ抽象クラスの継承が完了しました! 
ここからはコードの内容をみていきます。 

【Trainee.java】 

【TraineeMain.java】 

【実行結果】 

  • ・abstract の継承対象は、類似性の高いクラス 
    研修生には固定の作業 (何かの言語のカリキュラム) をこなしてもらいます。
    サンプルの抽象クラスでは研修生 (Trainee)に対して継承させました。 
    しかし、必要であれば研修後の社員、もしくは、本社勤務社員 ( Trainee 以外) にもカリキュラム自体をこなしてもらうことは可能です。 

類似という観点で言えば、研修生(大きなくくりで 「社員」)には名前がありますよね。 
社員には共通した情報(名前や年齢、 所属) があり、 クラスで言うところのフィールドとしての情報となります。 
そういった、 「インターフェースが持てない情報を扱える」という点において、似たような機能を持つインターフェースと抽象クラスを差別化することが可能です! 
また、初めに多重継承させたくない場合と説明しましたが、基本的に継承に関しては、インターフェースのように複数の実装はできません。 

「継承」と言う方法を選ぶこと、また、そのスーパークラスが 「抽象クラス」であることで、「多重継承を認めずに必須となる処理を実装させる」 という開発方法が取れる訳です ! 
インターフェースと違い、 相手 (処理を持たせたいクラス)を選ぶ書き方にはなってしまいますが、特定の大きな範囲で必須となる情報や処理を実装したい場合には安定した書き方になります! 

Step3: ポリモーフィズム 

大詰めです。 
今までの「インターフェース」、「抽象クラス」はポリモーフィズムの概念を理解するために学んできたと言っても過言ではありません! 

Step1:概念を知る 

  • 英語の意味 
    多態性、多相性、多様性 
  • Javaでの意味 
    「1つのスーパークラス(インタフェース)、複数のサブクラス (実装クラス)」 を表現するときに起こり得る現象のこと 

Step2: 使い方を知る 

やや具体性に欠けますのでサンプルを提示します。 
まずは以下の下準備を行います。 

1. アクセス修飾子が protected or public のメソッドを持つスーパークラスを作成 
 1-1. オーバーライドを強制したいので、 abstractで作成 

2. スーパークラスを継承し、 スーパークラスのメソッドがオーバーライドされているサブクラスを作成 
 2-1. サブクラスは2つ以上作成(※1つのみの場合は、ポリモーフィズムとなりません) 
 2-2. スーパークラスクラスのメソッドの処理に、サブクラスから呼び出されたことがわかる処理を実装 
 2-3. オーバーライドしたメソッド内の処理として、そのサブクラス専用の処理を実装 

3.スーパークラスを変数定義時のクラス (型) とし、 new する対象はサブクラスとする 

今回は 2-2 のパターンで実装していきます。 
すごく簡単にポリモーフィズムが確認できるサンプルを提示します ! 

【サンプル】 

【出力結果】 

今回は study パッケージで作成したクラスであるため、getClass()メソッドの取得結果にパッケージ名が付与されています。 
見た通りですが、インスタンスを生成するサブクラスに合ったクラスが出力されています。 
少しイメージできたでしょうか? 

では、更なる理解のために特別ゲストにご登場していただきます! 
あの大人気ゲームキャラクターです! 

ババーンっ! 

★のカー〇ィさんです! 

そして思い浮かべてください、、 

カー〇ィさんが敵を吸い込んで、吸い込んだ敵の能力を使う一連のシーンを! 

(★のカー〇ィさん を参照 

サンプル: ポリモーフィズム 

【手順】 

1.ポリモーフィズムのベースとなる AbilityOfEnemy を継承した敵クラスの作成 
2. メインクラス KirbyMain でインスタンスを生成し、メソッドをコール 

【AbilityOfEnemy.java】

PlasmaWisp.java】 

【BradeKnight.java】 

【KirbyMain.java】 

【実行結果】 

インスタンスを生成するクラスが変わることで、 抽象クラスの参照変数の中身も変わる 
敵のサブクラスが変わることで、カー〇ィさんの持つ能力が変化します! 
これが「ポリモーフィズム (=カー〇ィさん)」現象です! 
(無理やり感はありますが、イメージは大事です! )

ポリモーフィズムの必要性について 

ズバリ、 

「共通のメソッドを呼び出すが、 生成するオブジェクトによってその機能を変化させることが可能」という点です! 
ここで、あ!っとアハ体験できた方は、ポリモーフィズムの知識が理解へと移行しているはずです! 
自信を持っていきましょう! 

最後に 

今回みてきた内容は数あるデザインパターンと呼ばれる開発技法の根幹を担う知識となります。 
先人達が時間をかけ試行錯誤し生み出した、 開発者のための効率のよい開発方法です。 
Javaの基礎を理解していないと考え方が難しく馴染むまで時間がかかってしまう内容ではありますが、 
これらの知識・技術の修得は、Java上級者への道程となります。 

例題 

上記に提示したカー〇ィさんプログラムを作成し、実行しましょう。 

各クラスやインターフェイスは同一ファイルにまとめず、それぞれのファイルを作成してコンパイルしましょう! (可能であれば、自身でテーマを考えてオリジナルのポリモーフィズム現象を再現してみるのもいいでしょう。

目次