- トップページ
- 特集PC技術
- Java言語入門 ~C言語を学んだ君へ~
- [第10回] インタフェース
Java言語入門 ~C言語を学んだ君へ~
[第10回] インタフェース
今まで継承をメインに進めてきましたが、継承だけではどうしても駄目な点がありました。
そう、多重継承(class A extends B, C等)ができない点です。
その多重継承を解決するために用意されているものが、これから説明するインタフェースなのです。
この継承に似ているインタフェースがどういうもので、どのような機能があるか、どんな時に使うのかを覚えてください。
目次
- [1] インタフェースの基本
- [2] インタフェースの実装
- [3] インタフェースの継承
- [4] インタフェースの参照
- [5] インタフェースとポリモフィーズム
- [6] instanceof
- [7] 抽象クラスとインタフェース
- [8] 練習問題 第1問
- [9] 第1問解答
- [10] 練習問題 第2問
- [11] 第2問解答
- [12] 練習問題 第3問
- [13] 第3問解答
[1] インタフェースの基本
まずは、インタフェースがどういうものなのか説明します。
インタフェースとは、「定数」と「抽象メソッド」をひとまとめにしたもの
定数とは文字通り、変更不可の値のことです。第9回で説明しました、final(第9回参照)のことです。
抽象メソッドとは、オーバーライドを前提に定義したメソッドです。abstract(第9回参照)のことです。
では、このインタフェースをどのように使用するかを説明します。
まずは、次のクラス図を見てください。これは、誤った例です。
「人間」から「警察官」を、「犬」から「警察犬」を継承しています。
一見良さそうですが、このような継承の仕方は誤りです。理由は、
継承とは「系統」を表す
ものだからです。上の図では哺乳類の種類を系統化したものであり、
「警察官」や「警察犬」は哺乳類の継承に当てはまらないからです。
生まれた時から「警察官」の人はいません。
では、どうすればよいでしょうか。ここで登場するのが、インタフェースです。
継承は「系統」に使用しますが、インタフェースは「機能」として使用します。
つまり、人間と犬に「警察」という「機能」を付ければよいのです。
これで、正しい「警察官」と「警察犬」ができました。
もし、「医者」になりたければ医者のインタフェースを付けるだけです。
プログラムの世界は簡単に職業が選べます。
インタフェースの説明は以上です。
継承とインタフェースの違いはわかりにくいと思いますが、
以降で少しずつインタフェースの理解を深めてください。
インタフェースの基本形
インタフェースを定義するには、interfaceというキーワードを使います。
次のように記述します。
interface Name{ int VALUE = 10; // 定数 void method(); // 抽象メソッド }
Nameにはインタフェース名を書きます。
そして、「定数」と「抽象メソッド」はいくつ記述してもかまいません。
また、不思議に思ったでしょうが「final」を使わなくても、「int VALUE = 10;」で定数になります。
さらに「abstract」を付けなくても「void method();」で抽象メソッドになります。
インタフェースには「定数」と「抽象メソッド」のキーワードを意識する必要はない
この部分はとても大切なので覚えましょう。
そして、「抽象メソッド」は「機能」として使われるため、外部公開が必要になります。
したがって、上記の定義方法は以下の定義方法と全く同じ意味になります。
interface Name{ public static final int VALUE = 10; // 定数 public abstract void method(); // 抽象メソッド }
「定数」には「public static final」を、「定義」には「public abstract」を付けることがあらかじめ決まっています。
そのため、あえて書く必要はなく、省略ができます。
[2] インタフェースの実装
インタフェース内で定義した「抽象メソッド」に「中身を書く」ことを実装と言います。
では、実際に実装します。次のソースを見てください。
サンプルプログラム
// インタフェースA interface InterA { int VALUE_A = 10; void methodA(); } // インタフェースB interface InterB { int VALUE_B = 20; void methodB(); } // インタフェースを実装するクラス class AB implements InterA, InterB { // 実装 public void methodA() { System.out.println("methodAの実装"); } // 実装 public void methodB() { System.out.println("methodBの実装"); } } public class Java10_01 { public static void main(String args[]) { // クラスABの定数を表示 System.out.println(AB.VALUE_A); System.out.println(AB.VALUE_B); AB ab = new AB(); // クラスABのメソッドの呼び出し ab.methodA(); ab.methodB(); } }
実行結果
今回はインタフェースを2つ定義しました。インタフェースAとインタフェースBです。
そして、クラスABでインタフェースを実装してします。
インタフェースを実装するときはimplementsキーワード
クラスの時は「extends」を使いましたが、インタフェースの場合には「implements」を使います。
このとき、実装するインタフェースはいくつでもかまいません。
継承と違って複数実装することができるわけです。複数の場合は「,」で区切ります。
その後、指定したインタフェースにある抽象メソッドを実装、つまり「オーバーライド」します。
実装しなければ、コンパイルエラーが起こります。
クラスJava10_01では、クラスABにある定数と、メソッドを呼び出しています。
実行結果より、クラスABで定義しなかった定数も使用できることが確認できます。
[3] インタフェースの継承
インタフェースにも継承があります。継承をするには「extends」を使います。
これはクラスの継承と同じです。しかし、クラスと違って、インタフェースでは「多重継承」ができます。
次のソースを見てください。
サンプルプログラム
// インタフェースA interface InterA { int VALUE_A = 10; void methodA(); } // インタフェースB interface InterB { int VALUE_B = 20; void methodB(); } // インタフェースC(2つのインタフェースを継承) interface InterC extends InterA, InterB { int VALUE_C = 30; void methodC(); } // インタフェースを実装するクラス class AB implements InterC { // 実装 public void methodA() { System.out.println("methodAの実装"); } // 実装 public void methodB() { System.out.println("methodBの実装"); } // 実装 public void methodC() { System.out.println("methodCの実装"); } } public class Java10_02 { public static void main(String args[]) { // クラスABの定数を表示 System.out.println(AB.VALUE_A); System.out.println(AB.VALUE_B); System.out.println(AB.VALUE_C); AB ab = new AB(); // クラスABのメソッドの呼び出し ab.methodA(); ab.methodB(); ab.methodC(); } }
実行結果
インタフェースInterCがInterAとInterBを「多重継承」しています。
この場合、継承するごとに「,」で区切ります。
「継承」によって、インタフェースInterCは、3つのインタフェースの機能を持つことになります。
そのため、クラスABはインタフェースInterCのみを指定するだけで、
3つのインタフェースの機能を使えるようになります。
Javaはクラスの「多重継承」をサポートしていません。
その理由は複数のクラスの変数やメソッドを継承すると、機能が複雑になってしまうからです。
しかし、インタフェースは「定数」と「抽象メソッド」しか定義していません。
そのため、いくつ継承しても複雑にならず「多重継承」ができます。
インタフェースのアクセス修飾子
インタフェースにもアクセス修飾を付けることができます。次のように書きます。
public interface InterA { : }
[4] インタフェースの参照
前ページでインタフェースの基本的なことは分かったと思います。
では、インタフェースによるさまざまな使い方を説明します。
インタフェースの参照とは
インタフェースはクラスと異なり、インスタンス化はできません。
しかし、インタフェースを実装したオブジェクトをインタフェースの型が参照することはできます。
サンプルプログラム
interface Inter { void method(); } class L implements Inter { public void method() { System.out.println("Lのメソッド"); } } public class Java10_03 { public static void main(String args[]) { Inter inter; // インタフェースInter型を宣言 inter = new L(); // インタフェースInterがクラスLを参照 inter.method(); } }
実行結果
クラスJava10_03で、インタフェースinterがクラスLのオブジェクトを参照しています。
インタフェースの変数はこのような書き方ができます。
用途としては、「ポリモーフィズム」が実現できます。
これについては、次の項目で説明します。
[5] インタフェースとポリモフィーズム
ここでは、インタフェースを使ったポリモーフィズムの実現方法を説明します。
前項目でインタフェースの参照について説明しました。
そもそも、この参照とはポリモーフィズムを実現するための機能です。
では、どのように実現するのか、次のソースを見てください。
サンプルプログラム
// 職業:警察 interface Police { void investigate(); // 捜査する } // 警察官 class Policeman implements Police { public void investigate() { System.out.println("人間は聞き込みをする"); } } // 警察犬 class PoliceDog implements Police { public void investigate() { System.out.println("犬はにおいを辿る"); } } public class Java10_04 { public static void main(String args[]) { Police police[] = new Police[2]; // 配列生成 police[0] = new Policeman(); // 警察官生成 police[1] = new PoliceDog(); // 警察犬生成 for (int i = 0; i < police.length; i++) { police[i].investigate(); // 捜査命令! } } }
実行結果
ソース中に、インタフェースの参照が使われています。
実行結果より、ポリモーフィズムが確認できたと思います。
ポリモーフィズムについてはすでに第9回の継承で説明したので、特に説明することはありません。
注意点として、クラスJava10_04でインタフェースの配列を宣言しました。
これは、インタフェースをインスタンス化したのではなく、インタフェースの領域を確保したということです。
くれぐれも間違えないようにしてください。
[6] instanceof
インタフェースの参照について説明しました。
これは、インタフェース型の変数がオブジェクトを参照するというものです。
ところがこの参照をしている状態では、オブジェクト本来の型が何であったかわかりません。
そこで、使用するものが、instanceofです。これは次のように使います。
instanceofの形式
対象 instanceof 型名
「対象」には、調べたいオブジェクトを、「型名」には、対象と比較する型を入れます。
もし、「対象」が「型名」と一致した場合、「true」を返します。そうでなければ「false」を返します。
では、実際に使ってみます。次のソースを見てください。
サンプルプログラム
interface LAN { } class PC implements LAN { } class Printer implements LAN { } public class Java10_05 { public static void main(String args[]) { LAN lan[] = new LAN[2]; lan[0] = new PC(); lan[1] = new Printer(); for (int i = 0; i < lan.length; i++) { if (lan[i] instanceof PC) { System.out.println("パソコンです"); } else { System.out.println("パソコンではありません"); } } } }
実行結果
instanceofによって、配列に格納したオブジェクトが、クラスPCであるか、そうでないかを判定しています。
実行結果より、正しく判定できたことが確認できます。
[7] 抽象クラスとインタフェース
これまでに「ポリモーフィズム」を実現する方法をいくつか説明しました。
そして、実現のために使用したものに「抽象クラス」と「インタフェース」がありました。
どちらを使っても実現はできます。
そのため、この2つの違いがわかりにくかったかもしれません。
ここでは、この2つの使い分けをどのようにすればよいかを簡単に説明します。
まず、2つの特徴をそれぞれ説明します。
「抽象クラス」は「抽象メソッド」を含め、通常のメソッドや、変数なども定義できます。
しかし、クラスであるために、「系統」の異なるクラスへは適用できません。
それに対し、「インタフェース」はクラスの「系統」を気にせず、どのクラスにも適応できます。
しかし、「定数」と「抽象メソッド」しか定義できません。
つまり、簡単に説明すると、系統に従えるなら、「抽象クラス」を使います。
そうでなければ、「インタフェース」を使えばよいということです。
やはり、まだわかりにくいと思います。 Javaを使ってどんどんソースを書いていくと、違いがわかってくると思います。
[8]練習問題 第1問
以下の指示に従ってプログラムを作成しなさい。
なお、ファイル名はEx10_01.javaとする。
作成にあたっての条件
以下の条件を満たす、Nインタフェースを作成しなさい。
定数 :int型定数N(値は10とする)
抽象メソッド :bメソッド
上記のインタフェースが作成できたら、このインタフェースを実装したクラスEx10_01を作成しなさい。
*なお、メソッドの処理内容は自由に書いてよい。
[9]第1問解答
第1問解説
簡単なインタフェースが書けるかを確認する問題です。
特別難しいことはしていませんので、簡単に説明します。
1~4行目
インタフェースNを作成します。
このとき、修飾子はなくても構いません。付加する修飾子がすでに決まっているからです。
インタフェースは「定数」と「抽象メソッド」しか定義できません。
そのために修飾子を省略できるためです。
インタフェースの中身は、定数Nとbメソッドを記述しています。
インタフェースでは実際に実行する内容のメソッドは記述しません。
6~10行目
クラスEx10_01が自作したインタフェースNを指定して、bメソッドを実装しています。
インタフェースを実装するので、bメソッドをオーバーライドしなくてはならないわけです。
ここでは、"bメソッドの実装"と表示する処理を記述しました。
このとき、「public」修飾子を付けることに注意してください。
付けなければ、コンパイルエラーが起こります。
[10]練習問題 第2問
以下のプログラムの実行結果を答えなさい。
[11]第2問解答
第2問解説
instanceofキーワードの理解度を確認する問題です。
特別難しいことはしていませんので、簡単に解説します。
プログラムのメインの処理内容
1. インタフェースZ型の配列に3つのオブジェクトを格納する
2. 上記のオブジェクトの中で、クラスBのオブジェクトだけを探す
3. クラスBのオブジェクトのfメソッドを呼び出す
2.のクラスBのオブジェクトを探す時に、instanceofキーワードを使っています。
「instanceof」とはオブジェクトのクラス、あるいは実装したインタフェースが何であるかを調べるためのキーワードです。
これによって、クラスBのメソッドだけを呼び出しています。
[12]練習問題 第3問
以下の設問について〇か×で答えなさい。
1.インタフェースは変数と抽象メソッドを定義したものである
2.インタフェースは多重継承ができる
3.インタフェースはポリモーフィズムを実現する機能を持つ
[13]第3問解答
1.×
2.○
3.○
>第3問解説
基本的なインタフェースの理解度を確認する問題です。一問ずつ解説します。
1.インタフェースは変数と抽象メソッドを定義したものである?
答えは×です。インタフェースは「定数」と「抽象メソッド」を定義したものです。
2.インタフェースは多重継承ができる?
答えは○です。クラスとは違い、インタフェースは多重継承が可能です。
理由はインタフェースには、「定数」と「抽象メソッド」しか定義されていないため、
クラス内部が複雑にならないからです。
3.インタフェースはポリモーフィズムを実現する機能を持つ?
答えは○です。インタフェースの「参照」や「抽象メソッド」などがポリモーフィズムを実現しやすい環境を提供します。
コメント
*ςλιησηⅡ*
初めまして、*ςλιησηⅡ*と申します
[5] インタフェースとポリモフィーズム
とありますが、この部分以外のところは全て「ポリモーフィズム」となっているので、「ポリモフィーズム」ではなく、「ポリモーフィズム」へ統一したほうがいいのではないでしょうか
2016年8月 4日 23:25
コメントの投稿
トラックバックURL
http://www.isl.ne.jp/cgi-bin/mt/mt-tb.cgi/1079