![見出し画像](https://assets.st-note.com/production/uploads/images/43119052/rectangle_large_type_2_1750c830b91098afdcb4a8bd4171f773.png?width=800)
【Javaお勉強日記】インターフェイスについてまとめる
昨日のわたしへ。
継承については解ったけど、extendsじゃなくてimplementsのことあるよね
あれ何? の謎が解けます。
今日のわたしより。
インターフェイスとは何か
「詳しい実装知らなくても、そこを通せば目的のオブジェクトを操作できる入口」の概念。
例えば、お店にあるクレジットカードの処理用の機械。裏側で何が起きてるかは解らないけど、どのカード会社のクレジットカードでも、なんならデビットカードでも、「中でどんな処理してるかは知らないけど、そこを通せばクレジットカード決済ができる」とみんな知っている。
で、将来新しいカード会社が誕生したとしても、今あるインターフェイスを通れるように、「カードはこのサイズで作ってね」「この位置にICカードを入れてね」「こういう信号送ったらこういう情報返してね」というお約束を守って貰えれば、新しい機械を作ったり、機械の大改造をしなくても、新しいカード会社のカードを受け入れることができる。
じゃあ、Javaのプログラム中ではどう活躍するのか
例えば、BookとCdとGameと、FoodとPcというオブジェクトを扱わなきゃいけないとする。
それぞれのオブジェクトには、「ログにオブジェクトの内容を端的に表示する」という機能が欲しいとする。
そのため、実行クラスに「受け取ったオブジェクトの、ログ表示クラスを呼ぶ」という処理を入れたい。そのために、その実行クラスを通る可能性のあるオブジェクトには全部、ログ表示メソッドを入れちゃおう。
でも、こんどは「大丈夫?本当にそこに入ってくる全部のクラスにログ表示機能付いてる??」って心配になっちゃう。
それなら、「受け取れる型を制限しちゃって、絶対そのメソッドがある型だけを受け取れるようにしよう!」ってすればいいと思うじゃん。
でも、具体的に一つずつ「BookとCdとPcとFoodとGameしか通れないようにしました!!」ってすると、「今度Bagも必要になったから作ったよ!」ってなったときに、「Bagにはログ表示メソッドあるね、よし、じゃあリストに追加!」って一々手作業しないといけなくて、実用的じゃない…………
そこでインターフェイス型を作る
「ココを通るものは、必ずこのメソッドを備えておくべし」という「お約束」を書いてあるのがインターフェイス型。
このインターフェイス型を、使いたいクラスに埋め込んでおく(implements)することで、「私このメソッド絶対持ってます!持ってなかったらコンパイルエラー出してます!だから通してください!」「よし、通れ!」という事が可能になる。
具体的にどういう仕組みで受け取っているかというと
// インターフェイス型を定義する。public,もしくはパッケージアクセスにする。
interface Display{
// インターフェイス型の抽象クラスは全部 public abstract なので、一々書かない
void display(); // 絶対displayメソッドが必要だよ!という約束
}
// Displayインターフェイスを埋め込んだBookクラスを作る
class Book implements Display{
private String title;
private String author;
public Book(String title, String author){
this.title = title;
this.author = author;
}
// displayメソッドをオーバーライドする
@Override
public void display() {
System.out.println(this.title + "/" + this.author);
}
}
// 実行クラス
public class InterfaseTest {
public static void main(String[] args) {
// Book型のインスタンスだが、Display型を埋め込んであるので実はDisplay型でもある
Book book1 = new Book("本のタイトル","著者名");
displayTitle(book1);
}
// Display型で受け取るので、Displayインターフェイスで定義してある範囲だけ使える
public static void displayTitle(Display item){
item.display();
}
}
・まずDisplayというインターフェイスを作る
・Displayインターフェイスを埋め込んだBookクラスを作る
・実行クラス内で、Bookクラスのインスタンスを作る。このとき、Book型で作るが、インターフェイスを埋め込んであるクラスのインスタンスは、同時にインスタンス型も持つので、Display型でもある。
・汎用メソッドは、インターフェイス型で引数を受け取る。
こうしておくと、後々Cdクラスを作った時にもDisplay型を実装しておくことで、実行クラスを書き換えなくてもCdクラスが使えるようになる。
その際、うっかりdisplay()のオーバーライドを忘れた場合は、コンパイルエラーになるので、「うっかり忘れる」がなくなる。
インターフェイスの継承
インターフェイスは継承できる。
インターフェイス内には、「このメソッドを用意するように」というお約束しか書いていないので、あんまり深いこと考えず、多重継承とかしてもいい。
interface A extends B,C {}
という具合に書く。
この場合、インターフェイスAを実装したクラスは、A,B,C全てのインターフェイスに書かれているメソッドを全部オーバーライドしないといけない。
また、クラスに実装したインターフェイスは、サブクラスに引き継がれる。
スーパークラスAでインタフェースを実装し、メソッドaをオーバーライド
サブクラスBでメソッドaをさらにオーバーライド
という使い方も可能。
参考
「インターフェイスとは何か」については下記の記事が大変わかりやすかったです。
インターフェースとは?~継承とは役割が違う~|オブジェクト指向プログラミング(OOP)をおさらいしよう(3) - GiXo Ltd.
「「絶対必要なメソッド」なら継承で……いいのでは……?」と思ってしまって、しっくりこなくてうーんうーん、って思っていたのですが、こちらの記事で納得いきました。インターフェイスとは「お約束」だというのがポイントになりそう。
この記事が気に入ったらサポートをしてみませんか?