質問: ``` Javaのコードがわからないので質問しました。 1. クラスtestのinterface InterとクラスExpのInter aaaと書かれているのですが、何をしているのかわかりません。この処理の名称などがあれば、教えてください。 2. Expのインスタンスを生成し、iやsから変数を参照、またはreturnで変数を返すことはできますか。 よろしくおねがいします。 ``` ``` public class test { public interface Inter { public int Pass(); } class Exp{ public Inter aaa(int i, int j, String s) { return null; } } } ``` ### 補足情報(言語/FW/ツール等のバージョンなど) Java, Eclipse oxygen
回答: > > 何をしているのかわかりません > > > そもそも、ご質問のサンプルコードが、 何がしたいのか、意図が分かりにくいコードです。 「test」とか「aaa」とか名前が適当だし、 期待される返り値(の型)に反して、「null」を返しているとか、 いかにも書きかけっぽいです。お手本にすべきではありません。 元サンプルで大事なのは、**インターフェイス**だと思うので、 それが分かりやすくなるように、新サンプルを書き下ろしました。 ``` public class Machine { public interface Bottle { public String open(); } public Bottle select(int button) { Bottle product = null; if (button == 1) { product = new DrinkA(); } if (button == 2) { product = new DrinkB(); } return product; } private class DrinkA implements Bottle { public String open() { return "tea"; } } private class DrinkB implements Bottle { public String open() { return "coffee"; } } } ``` ``` class Client { public static void main(String args[]) { Machine vender = new Machine(); int button = 1; Machine.Bottle product = vender.select(button); String result = product.open(); System.out.println(result); } } ``` 上記サンプルコードを説明しますと、**自動販売機**をイメージしています。 購入者(クライアント)クラスから、自販機(マシーン)クラスを利用します。 ボタンを押すと、お茶かコーヒーが出てくるだけの、簡単な例です。 さて、インターフェイスがどのような意味を持っているかというと、 まず、「select」メソッドは、**インターフェイス型の(参照する)値を返し**ます。 今回の例では「Bottle」がインターフェイスで、「DrinkA」「DrinkB」が、 インターフェイスに規定された「open」メソッドを実装しています。 これによって、利用側の購入者クラスから、 **IF文を消し**ているし、「DrinkA/B」という**実装クラスも消し**ています。 これで、IF文で分岐して、newをベタ書きするのに比べて、**メンテナンス**しやすくなります。 なぜなら、**インターフェイスで実装から分離**されているので、 **利用側のクラスを変更しない**まま、実装クラスを交換できるからです。 それに今回の場合、「DrinkA/B」はprivateの内部クラスなので、 外部からインスタンスを勝手に作れないです。 これはひとりで書いていると意味が分かりにくいですが、 そもそも**Javaは、企業が開発して、企業が利用している、大規模開発向け言語**です。 そこで、自販機クラスを利用する側とされる側で、**別人や別組織**が実装している場合、 分離が非常に重要な意味を持ちます。利用する側にされる側の実装が入り込んでしまうと、 本体をクラスライブラリで**拡張**したいときなどに、本体がデグレする可能性が出てしまう。 だから、インターフェイスは実装が空だから、行数が多少増える、といった些細なことより、 実装から分離することの方が大事なんです。インターフェイスはJavaの中心的な機能です。 GOFも「**(実装ではなく)インターフェイスに対してプログラミングせよ**」と言っています。 **デザインパターン**を研究すると、こういう仕組みはよく分かります。 詳細は省きますが、上のコードは**ファクトリ**(メソッド)パターンを使ってます。 ``` Machine.Bottle product = vender.select(button); ``` もう少し裏側も見ておくと、インターフェイスで実装を切り離すことで、 利用側からIF文などが消えて**宣言的**に読めるのもメリットです。 上の一行を適当に意訳して読み下すと、 「販売機のボタンを選択した結果が、自販機向け飲料の製品である」 となります。翻訳調で不自然な日本語ですが、大筋の意味は通ると思います。 さらにたとえば、自販機にコインを投入する機能をつけたとして、 **1年後に読んでも**、「Bottle」と「Money」を取り違えることはまずないでしょう。 これが、「aaa」と「bbb」とかだと、どっちがどっちだか、すぐ分からなくなります。 書いているときは覚えていても、**長期間**に渡って**保守**すると負債になってきます。 また、名前が「aaa」などだと意味が分からないので、毎回実装を読む必要があります。 しかし、大規模は**コード量が大量**なので、なるべく**実装を読まないで使いたい**。 これには違和感があるかもしれませんが、標準ライブラリなどは、なるべく読みたくないでしょう。 それなら、自分たちのコードを標準ライブラリに近づければ、組みやすくなります。 **ドメイン**の言葉、業務の言葉、今回なら自販機を利用するシーンの言葉に近づけると、 利用しやすいし、**変更しやすく**なります。**人間が理解しやすい**からです。 まあサンプルなので、この例自体は微妙かもしれませんが、少なくとも、 質問文のサンプルコードの「aaa」とかよりは確実にマシだと思います。 もちろん、本番で書くときは、余裕さえあれば、ここからもっと、 ドメインに沿った命名にリファクタリングしていきます。 今回、「内部クラス(インナークラス)」や「ネストした型」に関しては、省略しました。 解説が中途半端にならないよう、インターフェイスの方を優先しました。 内部クラスはわりとマニアックな文法なので、下記リンクの解説記事に譲ります。 (ただもし、クラスが作れない環境とかだと多用せざるをえないかも......) * “ネスト”した型で始める軽量Javaプログラミング!? (1/3) - @IT * あなたの知らない、4つのマニアックなJava文法 (1/3) - @IT