SlideShare a Scribd company logo
1 of 41
Effective Java 輪読会 第3回
(項目18~22)
2013/12/18
開発部 野口
項目18
抽象クラスよりインタフェースを選ぶ
抽象クラスとインタフェース


抽象クラス
 実装を含むことができる
 サブクラス化が必要
 Java



は単一継承のみを許可している

インタフェース
 実装を含むことができない
 サブクラスである必要がない
インタフェースの利点(1/3)


新たに実装することが容易
 型階層に影響を及ぼさないため
 抽象クラスの場合、型階層に組み入れる必要がある



ミックスインを定義するのに理想的
 クラスが「本来の型」に加えて、なんらかの任意

の振る舞いを提供していることを宣言するために、
クラスが実装する型
 例)Comparable
インタフェースの利点(2/3)


階層を持たない型フレームワークを構築でき
る
 例)pp.91-92

SingerSongwriter

 抽象クラスで行うと、組み合わせ爆発が起こる!



安全で強力な機能エンハンスを可能にする
 ラッパークラスによって、継承しなくてもエンハ

ンスできる
 例)項目16

InstrumentedSet
インタフェースの利点(3/3)


抽象骨格実装クラスを提供することで、抽象
クラスの長所も取り入れることができる
 例)主要なコレクションインタフェース
 具象実装の例:



pp. 92-93 intArrayAsList()

擬似多重継承を用いることもできる
 ラッパークラスの応用形
抽象クラスの利点


発展させるのが容易
 たとえば、抽象クラスに具象メソッドを追加する

だけで、すべてのサブクラスがそのメソッドを提
供することになる
 インタフェースでは、そうはいかない。追加した時点

でコンパイルエラーになる
 インタフェースは、凍結前にできるだけ(多くのプロ
グラマが)実装することでテストすべき
まとめ(1/2)




インタフェースは、一般的に複数の実装を許
す型を定義する最善の方法
発展しやすさが、柔軟性と能力よりもより重
要だと考えられている場合は例外
 そのような場合は、抽象クラスを使用する
まとめ(2/2)




重要なインタフェースを提供するときは、骨
格実装の提供を検討しよう
publicインタフェースは細心の注意を払って設
計し、複数の実装を書くことで徹底的にテス
トしよう
項目19 型を定義するためだけにインタ
フェースを使用する
インタフェースの目的






インタフェースを実装するクラスのインスタ
ンスを参照するために使用できる型として機
能すること
実装するクラスのクライアントは何ができる
かを述べること
他の目的は、不適切
不適切なインタフェースの例


定数インタフェース
 「定数インタフェースパターンは、インタフェー

スの下手な使い方」
 実装の詳細であり、クラスのユーザには何の意味もな

いから
 (本来は不要な)負うべき義務を表しているから



定数が必要なくなっても、バイナリ互換性のためにその
インタフェースの実装が必要
疑問: 「バイナリ互換性のため」というのは、どういう意
味……?
→定数インタフェースを implements しているクラスに何

かしら影響がある
定数インタフェースを避ける


その定数が結びついたクラスやインタフェー
ス自体に定数を追加する
 例)Integer.MIN_VALUEやInteger.MAX_VALUE
 列挙されるものなら、enum

を使用する
 定数インタフェースよりは、ユーティリティクラ
スを使用する
インポートを活用すれば、長い修飾をすること
も回避できる

 static
項目20
タグ付クラスよりクラス階層を選ぶ
タグ付クラス


振る舞いを切り替えるためのタグを(enum
等のかたちで)メンバに持ち、そのメンバの
設定値に応じて各種操作に対する振る舞いを
switch 文で切り替えるようなクラス
 例)pp.98

Figure クラス
タグ付クラスは、冗長で、誤りや
すく、非効率(1/2)









enum 宣言、タグフィールド、switch 文と
いったお決まりのコードで散らかっている
複数の実装が単一クラスに詰め込まれ、読み
づらい
他の特性に属する関係のないフィールドに
よって、メモリ量が増加する
フィールドを自然に final にできない
フィールド初期化の正しさについて、コンパ
イラの助けを得られない
タグ付クラスは、冗長で、誤りや
すく、非効率(2/2)


特性の追加に際して、ソースの修正が必要
 OCP(Open-Closed

Principle / 開放-閉鎖の原

則)違反!




特性の追加に際して、すべての switch 文へ漏
れなく case 追加が必要
型から特性に関する手がかりが得られない
かわりにクラス階層を選ぼう


さっきのデメリット全部解消できます
タグ付クラスからクラス階層へ変
換するためのざっくりした3ステッ
プ






抽象クラスを定義する
特性ごとに具象サブクラスを定義する
抽象メソッドを個々の具象サブクラスで実装
する
例)pp.99 Figure / Circle / Rectangle クラス
See Also:


『リファクタリング』(Martin Fowler)
 サブクラスによるタイプコードの置き換え

によるタイプコードの置き換え
 ポリモーフィズムによる条件記述の置き換え
 State/Strategy
項目21 戦略を表現するために関数オブ
ジェクトを使用する
関数をパラメータ化する様々な機
構




関数ポインタ(C とか)
デリゲート(C# とか)
ラムダ式(Lisp とか)
関数オブジェクト


他のオブジェクトに対して操作を行うメソッ
ドを1つだけ公開するオブジェクト
 実質、そのメソッドへのポインタ
例:StringLengthComparator


文字列比較に対する具象戦略(concrete
strategy)
 状態を持たない
 よって、シングルトンにするとよい
戦略インタフェース


戦略を切り替えられるようにするために、具
象戦略が実装するインタフェース
 例)Comparator<T>



無名クラスを使用して宣言するのもよい
 ただし、インスタンス生成コストに注意
 名前がつけられないのもデメリットとなりうる
ホストクラス


具象戦略をprivateな内部クラスとして、イン
タフェースを通して外部に提供する
 例)pp.103

Host クラス

*疑問: pp.103の StrLenCmp はなぜ(何のために)
Serializable を実装しているのか?(単なる例示のため?
だとしたら、あまり良い例ではないような……)
→Comparator を Serialize して転送したいこともある!
まとめ








関数ポインタの主な使用方法は、Strategy パ
ターンを実装すること
Java での実装は、戦略インタフェースと、そ
れを実装する具象戦略クラス
具象戦略が1度しか使用されない場合は、無名
クラスを使用するとよい
繰り返し利用される場合は、ホストクラスを
導入するとよい
補足(1/2)


Java8ではラムダ式も使えるそうですね!
Before(pp.102):

Arrays.sort(stringArray, new
Comparator<String>() {
public int compare(String s1, String s2) {
return s1.length() - s2.length();
}
});
補足(2/2)


Java8ではラムダ式も使えるそうですね!
After(ラムダ式による記述):
Arrays.sort(stringArray,
(s1, s2) -> s1.length() - s2.length());
すっきり!
参考: http://dstn.appresso.com/developer/detail/?id=131
http://d.hatena.ne.jp/nowokay/20130824
項目22 非 static のメンバークラスより
static のメンバークラスを選ぶ
ネストしたクラス



他のクラス内に定義されたクラス
エンクロージングクラスに対して仕えるため
だけに存在すべき
 他の何らかの状況で有用ならば、トップレベルの

クラスであるべき
4種類のネストしたクラス





static のメンバークラス
非 static のメンバークラス
無名クラス
ローカルクラス
static のメンバークラス




エンクロージングクラスのメンバーのすべて
にアクセスできる
publicのヘルパークラスとして提供することも
できる
 例)pp.

104 Calculator.Operation
非 static のメンバークラス






メンバークラス生成時に、そのエンクロージ
ングインスタンスと関連付けられる
関連付けの際にメモリを消費し、インスタン
スの生成時間が増加する
アダプターの実装に用いることができる
 例)Map

values

インタフェースのkeySet、entrySet、
非 static のメンバークラスより
static のメンバークラスを選ぶ





エンクロージングオブジェクトへの関係のな
い参照を持たない
ガーベッジコレクションへの悪影響を防ぐ
public あるいは protected のメンバーの場合
は、あとから変更できないので特に慎重に選
ぶこと
無名クラス(1/2)






名前を持たない
エンクロージングクラスのメンバーではない
(static の文脈内で書かれたとしても)static
のメンバーを持つことはできない
宣言された箇所以外でインスタンス化できな
い
無名クラス(2/2)






instanceof やクラスの名前を利用できない
複数のインタフェースを実装したりできない
クライアントは、スーパータイプから継承さ
れたメソッド以外呼び出せない
短くあるべき(10行以下が目安)
無名クラスの用途


関数オブジェクトとして使用する
 See



also: 項目21

プロセスオブジェクトを生成する
 例)Runnable

インスタンス、TimerTask インスタ

ンス等


static ファクトリーメソッド内で使用する
 例)項目18の

intArrayAsList
ローカルクラス






ローカル変数が宣言できる場所すべてで宣言
できる
無名クラスと同様、static のメンバーを持てな
い
無名クラスと同様、短くあるべき
まとめ(1/2)






4種類のネストしたクラスがあり、それぞれ異
なる用途がある
メソッド内に収まらないようなものは、メン
バークラスにする
エンクロージングインスタンスへの参照が必
要なら、非staticにする
 そうでなければ、

static にする
まとめ(2/2)


メソッド内に属しているべきで、1箇所からの
み生成され、ベースとなる型が存在するな
ら、無名クラスにする
 そうでなければ、ローカルクラスにする

More Related Content

More from Appresso Engineering Team

マルチスレッド デザインパターン ― Single Threaded Execution
マルチスレッド デザインパターン ― Single Threaded Executionマルチスレッド デザインパターン ― Single Threaded Execution
マルチスレッド デザインパターン ― Single Threaded ExecutionAppresso Engineering Team
 
JavaScript 勉強会 ― 変数・演算子・文
JavaScript 勉強会 ― 変数・演算子・文JavaScript 勉強会 ― 変数・演算子・文
JavaScript 勉強会 ― 変数・演算子・文Appresso Engineering Team
 
Effective Java 輪読会 第7章 項目43-44
Effective Java 輪読会 第7章 項目43-44Effective Java 輪読会 第7章 項目43-44
Effective Java 輪読会 第7章 項目43-44Appresso Engineering Team
 
Effective Java 輪読会 第7章 項目41-42
Effective Java 輪読会 第7章 項目41-42Effective Java 輪読会 第7章 項目41-42
Effective Java 輪読会 第7章 項目41-42Appresso Engineering Team
 
Effective Java 輪読会 第7章 項目38-40
Effective Java 輪読会 第7章 項目38-40Effective Java 輪読会 第7章 項目38-40
Effective Java 輪読会 第7章 項目38-40Appresso Engineering Team
 
Effective Java 輪読会 第6章 項目35-37
Effective Java 輪読会 第6章 項目35-37Effective Java 輪読会 第6章 項目35-37
Effective Java 輪読会 第6章 項目35-37Appresso Engineering Team
 
Effective java 輪読会 第6章 項目32-34
Effective java 輪読会 第6章 項目32-34Effective java 輪読会 第6章 項目32-34
Effective java 輪読会 第6章 項目32-34Appresso Engineering Team
 

More from Appresso Engineering Team (20)

Effective Java 輪読会 項目74-75
Effective Java 輪読会 項目74-75Effective Java 輪読会 項目74-75
Effective Java 輪読会 項目74-75
 
マルチスレッド デザインパターン ― Single Threaded Execution
マルチスレッド デザインパターン ― Single Threaded Executionマルチスレッド デザインパターン ― Single Threaded Execution
マルチスレッド デザインパターン ― Single Threaded Execution
 
JavaScript 勉強会 ― 変数・演算子・文
JavaScript 勉強会 ― 変数・演算子・文JavaScript 勉強会 ― 変数・演算子・文
JavaScript 勉強会 ― 変数・演算子・文
 
JavaScript 勉強会 ― 型と値
JavaScript 勉強会 ― 型と値JavaScript 勉強会 ― 型と値
JavaScript 勉強会 ― 型と値
 
Effective Java 輪読会 項目69-70追加
Effective Java 輪読会 項目69-70追加Effective Java 輪読会 項目69-70追加
Effective Java 輪読会 項目69-70追加
 
Effective Java 輪読会 項目69-70
Effective Java 輪読会 項目69-70Effective Java 輪読会 項目69-70
Effective Java 輪読会 項目69-70
 
Effective Java 輪読会 項目66-68
Effective Java 輪読会 項目66-68Effective Java 輪読会 項目66-68
Effective Java 輪読会 項目66-68
 
Effective Java 輪読会 項目71-73
Effective Java 輪読会 項目71-73Effective Java 輪読会 項目71-73
Effective Java 輪読会 項目71-73
 
Java Day Tokyo 2014 まとめ (chen)
Java Day Tokyo 2014 まとめ (chen)Java Day Tokyo 2014 まとめ (chen)
Java Day Tokyo 2014 まとめ (chen)
 
Effective Java 輪読会 項目63-65
Effective Java 輪読会 項目63-65Effective Java 輪読会 項目63-65
Effective Java 輪読会 項目63-65
 
Effective Java 輪読会 項目60-62
Effective Java 輪読会 項目60-62Effective Java 輪読会 項目60-62
Effective Java 輪読会 項目60-62
 
Effective java 輪読会 項目57-59
Effective java 輪読会 項目57-59Effective java 輪読会 項目57-59
Effective java 輪読会 項目57-59
 
Effective Java 輪読会 項目49-52
Effective Java 輪読会 項目49-52Effective Java 輪読会 項目49-52
Effective Java 輪読会 項目49-52
 
Effective Java 輪読会 項目45-48
Effective Java 輪読会 項目45-48Effective Java 輪読会 項目45-48
Effective Java 輪読会 項目45-48
 
Effective Java 輪読会 項目53-56
Effective Java 輪読会 項目53-56Effective Java 輪読会 項目53-56
Effective Java 輪読会 項目53-56
 
Effective Java 輪読会 第7章 項目43-44
Effective Java 輪読会 第7章 項目43-44Effective Java 輪読会 第7章 項目43-44
Effective Java 輪読会 第7章 項目43-44
 
Effective Java 輪読会 第7章 項目41-42
Effective Java 輪読会 第7章 項目41-42Effective Java 輪読会 第7章 項目41-42
Effective Java 輪読会 第7章 項目41-42
 
Effective Java 輪読会 第7章 項目38-40
Effective Java 輪読会 第7章 項目38-40Effective Java 輪読会 第7章 項目38-40
Effective Java 輪読会 第7章 項目38-40
 
Effective Java 輪読会 第6章 項目35-37
Effective Java 輪読会 第6章 項目35-37Effective Java 輪読会 第6章 項目35-37
Effective Java 輪読会 第6章 項目35-37
 
Effective java 輪読会 第6章 項目32-34
Effective java 輪読会 第6章 項目32-34Effective java 輪読会 第6章 項目32-34
Effective java 輪読会 第6章 項目32-34
 

Effective java 輪読会 第4章 項目18-22