実装ではなくインターフェースへのコーディングの背後にあるポイントは、そうでなければプログラムを制約する実装の詳細の漏洩を回避することです。
コードの元のバージョンがを使用し、HashMap
それを公開した状況を考えてみましょう。
private HashMap foo = new HashMap();
public HashMap getFoo() { return foo; } // This is bad, don't do this.
これは、への変更getFoo()
はAPIの重大な変更であり、それを使用する人々を不満にさせることを意味します。あなたが保証しているのがそれfoo
がマップだけである場合は、代わりにそれを返す必要があります。
private Map foo = new HashMap();
public Map getFoo() { return foo; }
これにより、コード内での動作方法を柔軟に変更できます。foo
実際には、特定の順序で物事を返すマップである必要があることに気づきました。
private NavigableMap foo = new TreeMap();
public Map getFoo() { return foo; }
private void doBar() { ... foo.lastEntry(); ... }
そして、それは残りのコードのために何も壊しません。
後で何も壊すことなくクラスが与える契約を強化することができます。
private NavigableMap foo = new TreeMap();
public NavigableMap getFoo() { return foo; }
private void doBar() { ... foo.lastEntry(); ... }
これは、リスコフ置換原理を掘り下げます
代替可能性は、オブジェクト指向プログラミングの原則です。コンピュータプログラムでは、SがTのサブタイプである場合、タイプTのオブジェクトはタイプSのオブジェクトで置き換えられる可能性がある(つまり、タイプSのオブジェクトはタイプTのオブジェクトを置き換えることができる)そのプログラムのプロパティ(正確性、実行されたタスクなど)。
NavigableMapはMapのサブタイプであるため、この変更はプログラムを変更せずに実行できます。
実装タイプを公開すると、変更が必要な場合にプログラムの内部動作を変更することが難しくなります。これは苦痛なプロセスであり、多くの場合、後でコーダーにもっと苦痛を与えるだけの醜い回避策を作成します(私は、何らかの理由でLinkedHashMapとTreeMapの間でデータをシャッフルし続けた以前のコーダーを見ています-いつでも私を信頼してください私の心配するsvn非難であなたの名前を見てください)。
あなたはでしょう、まだ実装タイプを漏洩しないようにしたいです。たとえば、いくつかのパフォーマンス特性のために代わりにConcurrentSkipListMapを実装したい場合や、インポートステートメントなどではjava.util.concurrent.ConcurrentSkipListMap
なく、単に好きな場合がありますjava.util.TreeMap
。