Wiki内検索
カウンタ
メニュー
最近更新したページ
最新コメント
トップページ by awesome things!
トップページ by check it out
Generics(Java) by stunning seo guys
String(Java) by awesome things!
トップページ by check it out
PHPのページ by stunning seo guys
Tomcatのページ by stunning seo guys
トップページ by check it out
トップページ by awesome things!
タグ

インターフェイス(Java)

インターフェイス


はじめに

昔(1990年代後半くらい)に出版された書籍の中では「Javaは多重継承ができないので、Interfaceという多重継承の仕組みをもっている」などど書いてあるものがありました。そのため、Javaを始めた当初は「なんでこんなものがあるの」という感覚をもっていました。ですが、上に書いたようなインターフェイスの存在意義は「(その書籍の著者の)勘違い」か「説明不足」で、インターフェイスは、英語をそのまま解釈して「他のクラスとのインターフェイスを定義するもの」と解釈するのがもっとも適当であると、思っています。

私がこのように解釈がはじめてできたのは、デザインパターンについて勉強してみたときでした。最近では、多くの書籍が出版されていますので、1つくらい読んで見ると「目からうろこがおちる」のではないかと思います。

最近では、AOP(Aspect Oriented Programing;アスペクト指向プログラミング」や「ORマッピング」に絡んで「DAOパターン」といったインターフェイスをつかったプログラムが見直されています。

とはいえ、なかなか「感じ」がつかめないと思いますので、1つの例題を中心に「インターフェイスってこんなものなんだ」、「こんなことができるんだ」ということを実感してもらうことを目標に書きたいと思います。

インターフェイス

インターフェイスとは、上に書きましたように「他のクラスとのインターフェイスを定義するもの」です。インターフェイスは継承をすることができ、親子の関係をつくることができます(また、その際のルールはクラスと同じです)。また、クラスでは「単一継承」しかできませんでしたが、インターフェイスは複数をつかうことができます。インターフェイスを使うことをimplementする(まさに、実装するといいます)。

インターフェイスはクラスの宣言部で、「このインターフェイスを実装しますよ」という形式で宣言します。形式は以下です。

修飾子 class クラス名 extends 親クラス名 implements インターフェイス名1,インターフェイス名2{
    …
}

また、インターフェイスそのものは、以下のような形式をしています。

修飾子 interface インターフェイス名 extends 親インターフェイス名{
    …
}

インターフェイスはあくまで、「他のクラスとのインターフェイス(つまり、メソッド)」を規定するもので、その中にはメソッドのシグナチャだけを宣言し、メソッドの中身は実装しません。インターフェイスをimplementsしたクラスは、インターフェイスにあるすべてのメソッドの実装(implement)をする必要があります。

今回は、これまで使ってきたActorをクラスからインターフェイスを使った実装に変更し、そのインターフェイスをimplementsした何人かの登場人物を登場させて台詞を言わせたいと思います。

まずは、test.basic.beanにActorInterfaceを作ってみましょう。

ActorInterface.javaは次のようにしてください。

package test.basic.bean;

public interface ActorInterface {
    public String action();
    public void setWords(String str);
    public String getName();
}

これは、Actorにimplementsするインターフェイスなので、action()やsetWord()(台詞をセットする)といったメソッドを持ちます。また、役ごとに実装クラスを持つようにしますので、getName()でその役をとることにします。

さぁ、なにをやるかというところですが、てもとに「ハムレット」があったので、その中の一部(第3幕第2場黙劇後)からとってみることにしました。役者はハムレット(hamlet)とオフェリア(ophelia)、旅芸人の役者(Somebody)の3人です。また、舞台の様子を表現する部分があるので、それは黒子(Nobody)に語ってもらうことにしました。

これらから、test.basic.beanに以下のようにつくりました。これらは、基本的にnameというプロパティ値とコンストラクタ以外全て同じです。また、メソッドもActorInterfaceで規定されているもの以外は実装していません。

1.HamletImpl

package test.basic.bean;

public class HamletImpl implements ActorInterface{

    private String name = "Hamlet";
    private String words;

    // デフォルトのコンストラクタ
    public HamletImpl(){
    }

    public String action() {
        return words;
    }

    public void setWords(String string) {
        words = string;
    }

    public String getName() {
        return this.name;
    }
}

2.OpheliaImpl

package test.basic.bean;

public class OpheliaImpl implements ActorInterface{

    private String name = "Ophelia";
    private String words;

    // デフォルトのコンストラクタ
    public OpheliaImpl(){
    }

    public String action() {
        return words;
    }

    public void setWords(String string) {
        words = string;
    }

    public String getName() {
        return this.name;
    }

}

3.SombodyImpl

package test.basic.bean;

public class SomebodyImpl implements ActorInterface{

    private String name = "Actor";
    private String words;

    // デフォルトのコンストラクタ
    public SomebodyImpl(){
    }

    public String action() {
        return words;
    }

    public void setWords(String string) {
        words = string;
    }

    public String getName() {
        return this.name;
    }

}

4.NobodyImpl

package test.basic.bean;

public class NobodyImpl implements ActorInterface{

    private String name = " ";
    private String words;

    // デフォルトのコンストラクタ
    public NobodyImpl(){
    }

    public String action() {
        return words;
    }

    public void setWords(String string) {
        words = string;
    }

    public String getName() {
        return this.name;
    }

}

次に、これらを演じてもらうmainメソッドを用意する必要があります。test.basicにSample021を作成し、以下のようにコードをいれてみてください。

package test.basic;

import java.util.ArrayList;
import java.util.Iterator;

import test.basic.bean.ActorInterface;
import test.basic.bean.HamletImpl;
import test.basic.bean.NobodyImpl;
import test.basic.bean.OpheliaImpl;
import test.basic.bean.SomebodyImpl;

public class Sample021 {
    public static void main(String[] args) {
        ArrayList aList = new ArrayList();

        // 台詞の設定
        ActorInterface o1 = new OpheliaImpl();
        o1.setWords("ハムレット様、あれはどういう意味でございます?");
        aList.add(o1);

        ActorInterface h1 = new HamletImpl();
        h1.setWords("いや、それ、あれはいかさま、いわば意味なきいたずら。");
        aList.add(h1);

        ActorInterface o2 = new OpheliaImpl();
        o2.setWords("どうやらお芝居のあらすじらしゅうございます。");
        aList.add(o2);

        ActorInterface n1 = new NobodyImpl();
        n1.setWords("まくの前にひとりの役者が現れる。王と妃、それに注意する。");
        aList.add(n1);

        ActorInterface h2 = new HamletImpl();
        h2.setWords("こいつの話で万事が分かる。役者に秘密は守れない。何もかも喋ってしまうぞ。");
        aList.add(h2);

        ActorInterface o3 = new OpheliaImpl();
        o3.setWords("いま見せてくれたお芝居の意味も?");
        aList.add(o3);

        ActorInterface h3 = new HamletImpl();
        h3.setWords("(荒々しく)もちろんだ、そのほか何でも教えてくれよう、おまえのほうから見せてやりさえすれば \n"+
            "片端からな−−お前さえ恥ずかしがらずに見せてやれば、やつも恥じずにこれはこうと教えてくれるものだ");
        aList.add(h3);

        ActorInterface o4 = new OpheliaImpl();
        o4.setWords("また、そのような、私はお芝居を見ることにいたします。");
        aList.add(o4);

        ActorInterface s1 = new SomebodyImpl();
        s1.setWords("われら一座のため、また、ここに演じます悲劇のため、寛大なるご見物のみなさまがた\n"+
            "なにとぞ多少の不出来はお許しくださいますよう。(退場)");
        aList.add(s1);

        ActorInterface h4 = new HamletImpl();
        h4.setWords("あれは、口上か指輪の銘か。");
        aList.add(h4);

        ActorInterface o5 = new OpheliaImpl();
        o5.setWords("本当にみじこうございますこと。");
        aList.add(o5);

        ActorInterface h5 = new HamletImpl();
        h5.setWords("女の恋のように。");
        aList.add(h5);

        // アクション
        Iterator it = aList.iterator();
        while(it.hasNext()){
            ActorInterface tmp = (ActorInterface)it.next();
            String name = tmp.getName();
            String action = tmp.action();
            System.out.println(name + ";" + action);
            System.out.println("\n");
        }

    }
}

それではこれを実行してみてください。以下のように出力されましたか?

Ophelia;ハムレット様、あれはどういう意味でございます?


Hamlet;いや、それ、あれはいかさま、いわば意味なきいたずら。


Ophelia;どうやらお芝居のあらすじらしゅうございます。


  ;まくの前にひとりの役者が現れる。王と妃、それに注意する。


Hamlet;こいつの話で万事が分かる。役者に秘密は守れない。何もかも喋ってしまうぞ。


Ophelia;いま見せてくれたお芝居の意味も?


Hamlet;(荒々しく)もちろんだ、そのほか何でも教えてくれよう、おまえのほうから見せてやりさえすれば
片端からな−−お前さえ恥ずかしがらずに見せてやれば、やつも恥じずにこれはこうと教えてくれるものだ


Ophelia;また、そのような、私はお芝居を見ることにいたします。


Actor;われら一座のため、また、ここに演じます悲劇のため、寛大なるご見物のみなさまがた
なにとぞ多少の不出来はお許しくださいますよう。(退場)


Hamlet;あれは、口上か指輪の銘か。


Ophelia;本当にみじこうございますこと。


Hamlet;女の恋のように。


「台詞の設定(ながくなって恐縮です)」は本質的ではありません。アクションのところに注目してください。台詞の設定でArrayListにいれた役者(実装クラス)は4種類ありましたが、(if文を含まずに)1つのループで全ての役者が台詞を言うことができました。「こういうコーディングができるんだぁ」と思われた方もいらっしゃると思います。ポイントは「インターフェイスでメソッドを規定したこと」、「(実装クラスではなく)インターフェイスを型として用いたこと」です。この2つによって、異なる実装クラスが1つのインターフェイスを通じて、まったく同じに扱われていることが分かります。役者が増えたとしてもアクションの部分に変更はいりません。

インターフェイスをうまく使えるか、否かでシステムの設計が大きく変わります。いきなりは無理でしょうから、はじめの内は、実装クラスがなんとなく似ているときに「メソッドを(抽象化したら)共通化できるかな」といった視点で見ていければ、グッドなのではないかと思います。
2007年02月26日(月) 15:40:00 Modified by wanderingse




スマートフォン版で見る