インターフェースについて(java)

javaをはじめとするオブジェクト指向の言語に特有の

ポリモーフィズム(多態性)とインターフェースの関係について

「はじめてのjava入門」他、参考サイトを見ても、「インターフェース」ってそういうことではないのでは、、という事例をたくさんみかけたので、備忘録的に自分の考え方と、ソースをこの記事に残しておく。

(念のため付け足しておきますが、java勉強歴は1週間ほどです。。)

【参考サイト】

①「浅煎りコーヒーJavaアプリケーション入門」http://msugai.fc2web.com/java/interface.html 結論、このサイトが一番ピンときた。

②@IganinTeaさんの記事

https://qiita.com/IganinTea/items/e1d35db0a14a84bda452 この方のソースも「インターフェース」って、そういうことだよね、と納得できるものでした
内容的に、私にはまだ難しいのですが、、ソースでのインターフェースの使い方には納得できました。

③「はじめてのjava入門」http://www1.bbiq.jp/takeharu/java104.html

※なんとなく、あまりあてにならないかな、、と思い始めたサイト

「はじめて」と「入門」も同意反復だし、、あえて?

概念的に「インターフェース」ではなく、継承だよね、という例でした。

④「侍」https://www.sejuku.net/blog/21542

③同様、こんな初心者が言うのもあれですが、インターフェースの使い方が「??」の例です。「それは継承の例では?」。

インターフェースとは?

参考サイト①によると

「インタフェースは、ロジックを持たずに、パッケージpublicなメソッドのシグネチャのリストです。」とのこと。

シグネチャとは、「署名」を意味しますから、インターフェースとは

「同一パッケージ内で使用できるメソッドの名称一覧」と言っています。

なんとなく、僕はこの説明が一番腑に落ちました。

インターフェースにおいて、メソッドは名称のみ定義されています。

メソッドのロジックは、インターフェースを実装(implements)するクラスにおいて、オーバーライドする必要があります。オーバーライドしないと、コンパイルエラーとなります。「実装の強制」ができる、ということです。

つまり、このインターフェース(ふるまい)を実装したんだから、

ちゃんとふるまえるようにしろ」ということですね。

ここまできて、「継承」との違いがなんとなくわかってきたのですが、「継承」は、「動物」→「猫」のような上位下位の関係を概念的に、表す意味があります。あと、「コードを書く」と作業に対しては「記述の重複を防ぐ」というのが一義的な意味です。

継承してオーバーライドすれば、確かにインターフェースと同じように、継承先で「ふるまい」を変えることもできるのですが、、これはインターフェースでやるべきです。また、継承は一つのクラスからしかできませんが、インターフェースは、複数適用することができます。

継承を使用するときは、サブクラスが、スーパークラスと大体同じようにふるまうが、少しだけ変えたい、というように、あくまでも「記述の重複を防ぐ」という一義的な目的に沿うようなときに使うべきなのでしょう。

なお、インターフェースに近い概念として、抽象クラスがあります。参考サイト②にあるような、実装する際の勘所というのは、まだ私にはつかめないところもありますが、そもそもの発想が異なる、と覚えておくこととします。

インターフェースは「ふるまい」の一覧であり、上位下位の関係は意識していません。(多分)なので、この上位下位の関係性については、フォルダ構成などでうまく表現していく必要があるのでしょう。(また勉強してみます。)

最近の新しい言語(Go言語など)では、抽象クラスがなくなっているそうですね。インターフェースは比較的新しい考え方であり、継承→抽象→インターフェース(ふるまいを与える)とオブジェクト指向言語も進化をしているのだな、くらいの理解にとどめておいたほうがいいのかもしれません。。プログラミング初心者にとっては、この「歴史」が学習のネックとなってきますが、、掘れば「こういう歴史があってな」という記事はいくらでもでてきますので、疑問におもったらすぐ調べ、一つ一つ疑問を解消していけばいいのでしょう。

インターフェースは、クラスに「ふるまい」を与えることができる。

インターフェースは「runnable」に代表されるように、よく「~できる」という名称がつけられています。直訳すると「走ることができる」、ですね。つまり、この「runnable」というインターフェースを実装したクラスは、「走る」というふるまいができるようになる、ということです。

例として、僕が作成したサンプルソースを下部に添付しておきます。このサンプルソースでは、「barkable」→「吠えられる」という「ふるまい」をインターフェースとして実装してみました。

barkableというインターフェースではbark(吠える)というメソッドを定義しています。先に説明したとおり、bark内にはロジックは記述しておりません。

その下で、LionとCatというクラスを用意しています。この2つのクラスに、barkableというインターフェースを実装することで、このクラスに「吠える」というふるまいをさせることができます。

なお、インターフェースを使用する際に、大事なのが、Lion、Catを呼び出すクラスでは(サンプルソースでいうとMyAppというクラス)、Runnableインターフェースが実装されているということさえ、わかっていれば、Lion、Cat内でのbarkメソッドの実装を意識することなく、Lion、Catにbark(吠え)させることできるのです。(実装を隠蔽することを、カプセル化といいます)

パッケージ内で利用可能なのですから、他のクラスで、他の動物に吠えさせたいときは、barkableを実装し、barkメソッドを使ってやれば、好きな吠え方をさせられるし、barkableを実装しているクラスだとわかっていれば、いくらでも吠えさせることができるのです(笑)

【サンプルソース】

interface barkable{

  void bark();

}

class Rion implements barkable{

@Override
public void bark(){

System.out.println("ガオー!!");

}

}

class Cat implements barkable{

@Override
public void bark(){

System.out.println("ニャオー!!");

}

}

public class MyApp{

public static void main(String[] args){

//このように実装を意識せず「吠えさせる」というふるまいを記述

//確かに可読性も高いです

Rion ri = new Rion();
ri.bark();

Cat ca = new Cat();
ca.bark();

}

}

【実行結果】

[vagrant@localhost java_lessons]$ javac MyApp.java
[vagrant@localhost java_lessons]$ java MyApp
ガオー!!
ニャオー!!

参考サイトについて

悪い例として参考サイト③参考サイト④を紹介しました。

参考サイト③では、Animalをインターフェースとして定義しています。Animalというのは「モノ」を表します。「動物としてのふるまい」を定義している、とも解釈できますが、インタフェースの概念にはなじまないのかな、、と思いました。(そこから、動物でインターフェースを表現するなら、、とサンプルソースを書いてみた次第です。)

参考サイト④では、calc(計算)というインターフェースを作成しています。
それをAdd(足し算)、というクラスに適用しています。

どちらかというと、「計算」というクラスに、「足し算」というふるまいを適用させたほうが、「インターフェース」という概念にフィットするサンプルになりそうです。

あと「ふるまいの名称」であるメソッドの名称がmethod1、method2では、インターフェースの意味がない気がします。。「ふるまいの名称の一覧」なので、ふるまいとして、わかりやすい「名称」としあげることは、インターフェースの説明として、必要不可欠です。

ものすごい混乱するから、やめて!

この記事が気に入ったらサポートをしてみませんか?