仮にAというinterfaceを作りそれを仮にBというクラスが継承したとします。Bのインスタンスを仮にCクラスのメソッドsetA(A a)というメソッドでCのメンバー変数にAクラスとしてセットします。コードにすると雑ですが、下記みたいな感じでしょうか。
interface Aは実装上なくても問題ないしむしろ邪魔に思えるのですが、CがBのインスタンスをAとして扱えるために余計なBのメソッドを呼べないので疎結合だからいいのだそうです。私は勉強不足の為わかった様なわからんような気分なんですが、interfaceはある程度、活用性がないと作る意味ない気がします。例えばD,E,Fのクラスがあってそれらも、Aのinterfaceを継承して他のクラスに使わせるならわかる気がします。でも、Bのみしか継承しないのだったらいらないと思うのです。
こういうのはリファクタリングのテクニックなんですか。そんなに重要なんでしょうか。テクニックの名前とかありますか。
java
1interface A {} 2 3class B implements A {} 4 5class C { 6 A a; 7 void setA(A a) { 8 this.a = a; 9 } 10} 11 12~~~~ 13 B b = new B(); 14 C c = new C(); 15 c.setA(b); 16~~~~
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答7件
0
ベストアンサー
余計なメソッドを呼べなくするのが疎結合なわけではないです。
メソッドを公開したくなければ、privateにすればいいだけなので。
疎結合とは、依存関係がない、というものです。
依存とは、import文であったり、new と書いている部分のことです。
ようは、「そのクラスが削除されたとしても、コンパイルエラーにならない」
という関係が疎結合です。
この例でいうと、Bクラスが消えても、Cクラスには影響がないということです。
つまりインターフェースを使った設計にしておくと、
呼び出し元に影響を与えずに、
必要なものはそのインターフェースを実装して追加すればいい、
不要なものは削除すればいいようになるところが嬉しいのです。
逆の密結合は、仕様変更や拡張に非常に弱く、一部のプログラムを直すだけで、
そこら中をテストし直す必要があったりと、大手術になることが多いです。
例えばD,E,Fのクラスがあってそれらも、Aのinterfaceを継承して他のクラスに使わせるならわかる気がします。
そうですね。その通りだと思います。
なので、普通はyubaさんのおっしゃっていることが多いです。
今後増えることを想定としているため、インターフェースを決めている。ということです。
###悪い例
java
1public class PC { 2 public void setKeyboard(Keyboard keyboard) {}; 3 4 public void setMouse(Mouse mouse) {}; 5} 6 7public class Keyboard {} 8 9public class Mouse {} 10
###良い例
Java
1public class PC { 2 public void setUsbDevice1(USB usb) {}; 3 4 public void setUsbDevice2(USB usb) {}; 5 6 public void setUsbDevice3(USB usb) {}; 7} 8 9public class Keyboard implements USB {} 10 11public class Mouse implements USB {} 12
現実の世界でも、周辺機器が増えたからPCに修理がいるというのは不便なわけです。
【悪い例】
プリンターを買ったから、PCにプリンタ用の穴(setPrinter)をつけてもらうように修理に出す。
【良い例】
プリンターを買ったけど線がUSBだったから、そのままPCに接続できた。
PCの修理は不要。
周辺の部品が、使う側に影響を出さないという設計がいいんです。
投稿2016/03/17 05:43
総合スコア4666
0
A,B,Cクラスを作るのが別々の人だとしたらどうでしょう?
Cクラスの作者とAクラスの作者は並行して別々に開発します。あとで結合することを考えればCの作者は「どんなクラスを作ってもいいけどBインターフェイスとして実装してくれ」とあらかじめ頼んでおけばいいわけです。
これは特殊なケースではありません。ライブラリを作る場合、ライブラリ作者がA,Cの作者にあたり、利用者がB作者に当たることになります。
投稿2016/03/16 23:43
総合スコア5568
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
結果的に不要だっただけで、先にinterfaceAと受け入れクラスCを作って、全体を作ってから、差し込むBを作ったのだけど、実際は1つのクラスでしか使わなかった・・という感じだと、そうなります。
最終的に無駄なら削っていいわけなのですが、他人のソースコードを読むときには、どうやって作っていったのだろう・・という視点がないと何をしているのかわからないことがあります。
投稿2016/03/16 21:19
総合スコア234
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
退会済みユーザー
2016/03/21 08:55
0
疎通性ではなく疎結合ではないでしょうか?
共起語としては DI なんかでぐぐるとよいかも。
あとリファクタリングのテクニックとは言わないような… (別の用語を混ぜて覚えている??
よくある目的は、実装を交換可能にすることです。
実装を交換可能にすると
- A と C が汎用的な機能であれば、再利用性があがる。
- A が C に対し必要最小限の機能で構成されている場合、可読性が上がり理解しやすいコードになる。
- 目的に合わせて A の実装 (B その他クラス) を入れ替えることができる。
などが良い感じです
↑ 3. の補足ですが、例えば性能特製によって目的ごとに実装を交換するだとか
本番コードとテストコードを入れ替えやすいとかですかね
投稿2016/03/16 16:30
編集2016/03/16 16:33総合スコア94
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
退会済みユーザー
2016/03/17 00:10
0
例にあるようなパターンの場合は、多分不要なでしょうね。
Bを渡すのに、Aを引数とするメソッドを定義している場合、いくつかの理由が考えられます。
例えば、Iteratorパターンがそうで、B以外にもCを使って似たようなことをしたいクラスが複数あり、Cで共通して使いたいメソッドをまとめたものをAとして定義した場合です。
または、例のコードとは違いますが、FactoryMethodパターンの場合にはありえます。実際のクラスを隠してわたす場合で、Bの状態変更をパッケージ内に限定したい場合などにも有効です。
Rubyやjavascriptはインターフェイスを持っていないので、実はそれほど大事なテクニックでも無いかもしれません。ですが、私は使う必要のないメソッドを晒して使う側を混乱させないようにするには良い方法だと思います。
投稿2016/03/16 16:06
総合スコア2883
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
退会済みユーザー
2016/03/29 15:49
2016/03/30 07:29
退会済みユーザー
2016/03/30 12:25
0
リファクタリングというより、テクニックでしょうか。
知っている中では、Immutable Interface(イミュータブル・インタフェース)という手法と本質は同じだと思います。
下記のようなインタフェースとそれを実装したクラスがあったとします。
関数の戻り値などで、ImmutableA型を返すか、A型を返すかによって、権限機能(編集できる権限、閲覧のみの権限)などに応用できます。
(といっても、ImmutableA型をA型にキャストするような使い方をされると意味ないので、実装する側が間違えないようにするための工夫だと思ってます。
Immutable Interfaceに関して詳しい方居ましたら補足お願いしたいです。)
Java
1// インスタンスの内容を読み取り専用にするインターフェース 2Public Interface ImmutableA{ 3 public String getName(); 4 public int getNum(); 5}
Java
1Public class A immplements ImmutableA{ 2 private String name; 3 private int num; 4 5 public String getName() {return name}; 6 public int getNum() {return num }; 7 public void setName(String name) { this.name = name; } 8 public void setNum(String num) { this.num = num} 9}
投稿2016/03/16 16:05
編集2016/03/16 17:06総合スコア907
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
退会済みユーザー
2016/03/29 15:53
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2016/03/16 15:43
退会済みユーザー
2016/03/16 15:54 編集
2016/03/16 15:56
退会済みユーザー
2016/03/21 09:06
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
退会済みユーザー
2016/03/21 08:58 編集