ArrayList<Class> name = new ArrayList<Class>(#)
昨日誰かが私に、このようなことは悪い習慣であり、次のように「インターフェースに対して」プログラムする必要があると言いました。
List<Class> name = new ArrayList<Class>(#)
彼はどういう意味ですか?
ArrayList
を実装しList
ます。したがって、List
いくつかの理由で使用するのが最善です。たとえば、将来リストのタイプを変更したい場合(たとえば、、、、またはを使用することLinkedList
にした場合)、割り当ての右側を変更するだけで、残りのコードは変更されずに機能します。Stack
Vector
使用しているリストの正確な実装を明らかにする必要はありません。
使用できるメソッドは、インターフェースからのメソッドのみです。技術的にはそれほど重要ではありませんが、従うのは良い習慣です。コードはよりクリーンで保守が容易です。
そのコードスニペットの「インターフェース」はList
、より抽象クラスですArrayList
。
Listは、ArrayList、LinkedListなどの他の多くのクラスによって実装されます。
インターフェースを使用して宣言することによりname
、ユーザーは実際にname
どのタイプのリストであるかを知る必要がなくなり、将来別のタイプのリストを使用することにした場合でも、コード内の多くの場所を変更する必要がなくなります。name
List<Class> name = new ArrayList<Class>(#)
SuperType ref = SubTypeObj
これは、ArrayListを作成する多態的な方法です。ListはArrayListのスーパータイプです。このような配列リストを作成する利点は次のとおりです。
後で同じリストを参照してLinkedListを作成できます。
name = new LinkedList(#)
理想的には、コレクション変数と戻り値の実装ではなく、コレクションのインターフェイスを使用する必要があります。あなたの例では、それはそれほど大きな問題ではありません。それがより有用になるのは、メソッドを書くときです。
public List<String> doSomething() {
}
を使用することList<String>
でArrayList<String>
、このメソッドは使用する別のリストを選択できますが(たとえば、LinkedListに変更される可能性があります)、APIのコントラクトは変更されないため、メソッドが別の種類のリスト。
In Interface は、使用可能なメソッドを定義するため、クラスを記述してインターフェイスを実装する場合は、インターフェイスでメソッドを定義する必要があります。(他の方法もあるかもしれません)
他の人が使用するクラスを作成し、次のようなメソッドがあるとします。
public void doSomething(List<Thing> aListOfThings) {
//some code to manipulate the list
}
他の人があなたのクラスを使用するコードを書くとき、あなたは、彼らがあなたのメソッドを呼び出すためにどのタイプの List を使用したかを正確に気にする必要はありません。これらはすべて有効です。
yourClass.doSomething(new ArrayList<Thing>());
yourClass.doSomething(new AttributeList<Thing>());
yourClass.doSomething(new Vector<Thing>());
yourClass.doSomething(new SomeOtherTypeOfList<Thing>());
目的に適したリストのタイプ (実装) を自由に選択できます。
彼は、必要な変数のタイプだけを使用する必要があることを意味しました。たとえば、でのみ定義されているメソッドを使用している場合を除き、を使用するArrayList
必要がありますList
。同様に、そこから来るものが必要ない場合は、などList
を使用します。Collection
これには2つの理由があります。
1)将来、実装を別のタイプに変更するのが簡単になります。を使用するORMを使用しているとLazilyLoadedList
しましょう。すべてのコードが反対の場合は、問題なくList
スロットに入れることができます。反対の場合は、多くのメソッドシグネチャを変更し、特定のメソッドArrayList
に依存していないことを確認する必要があります。ArrayList
これは何の一部です
2)JMockやMockitoなどのツールを使用すると、インターフェイスのモックが簡単になります。
これは、インターフェイスとは何か、ソフトウェア開発でどのように役立つかを理解するのに役立ちます。
パッケージを誰かに郵送する必要があるとしましょう。多くの運送業者オプションがあります: USPS、UPS、FedEx など。
ここで、パッケージをドロップできる中央のメールボックスが 1 つあり、すべての運送業者がそのメールボックスから配達できると想像してください。したがって、USPS、UPS、または FedEx がどのように集荷するかは気にしません。あなたがする必要があるのは、パッケージをメールボックスに持ってきて、それをドロップすることだけです. 実際にどのように配信されるかは、あなたには関係ありません。
この例では、インターフェイスを次のように定義できます。
public interface IMailService
{
void SendMail(obj myMailObj);
}
そして、次のように定義された MailService の具体的な実装を持つことができます。
public class USPSMailService : IMailService
{
public void SendMail(obj myMailObj)
{
//This code executes SendMail using USPS' implementation
}
}
public class UPSMailService : IMailService
{
public void SendMail(obj myMailObj)
{
//This code executes SendMail using UPS' implementation
}
}
public class FedExMailService : IMailService
{
public void SendMail(obj myMailObj)
{
//This code executes SendMail using FedEx's implementation
}
}
次に、コードでメールを送信する場合は、次のように記述します。
IMailService mailService = new FedExMailService();
mailService.SendMail(myMailObj);
後で UPS のメール サービスを使用する必要がある場合は、UPS タイプでインスタンス化するだけです。SendMail() へのすべての呼び出しを含む残りのコードは変更されていません。
mailService = new UPSMailService();
ここで、UPS が他の運送業者が提供していないサービスを提供している場合、変数を具象型として定義する必要があります。
たとえば、UPS クラスが次のように定義されているとします。
public class UPSMailService : IMailService
{
public void SendMail(obj myMailObj)
{
//This code executes SendMail using UPS' implementation
}
//This is a method that only UPS offers
public void SendMailOnSunday(obj myMailObj)
{
//This code executes UPS' proprietary method
}
}
次に、コードで具象クラスをそのまま使用する必要があります。
UPSMailService mailService = new UPSMailService();
mailService.SendMailOnSunday(myMailObj);