0
ArrayList<Class> name = new ArrayList<Class>(#)

昨天有人告诉我,这样的做法是不好的做法,我应该“针对界面”进行编程,如下所示:

List<Class> name = new ArrayList<Class>(#)

他是什么意思?

4

8 回答 8

3

ArrayList实现ListList因此,出于多种原因,最好使用。例如,如果您希望将来更改列表的类型(例如,您决定使用 a LinkedListStackVector),您只需要更改赋值的右侧,其余代码就可以正常工作,不变。

于 2013-01-04T14:07:17.640 回答
3

无需透露您正在使用的 List 的确切实现。

唯一可用的方法是接口中的方法。从技术上讲,这并不重要,但这是一个很好的习惯。代码更干净,更易于维护。

于 2013-01-04T14:07:32.720 回答
2

该代码片段中的“接口”是List一个比ArrayList.

List 将由许多其他类实现,如 ArrayList、LinkedList 等......

通过使用接口来声明name,那么用户name不必知道列表name实际上是哪种类型,并且如果您决定将来使用不同类型的列表,您可以不必更改代码中的很多地方。

于 2013-01-04T14:10:33.073 回答
1

理想情况下,您希望使用集合的接口而不是集合变量和返回值的实现。在您的示例中,这不是什么大问题。在编写方法时,它确实变得更有用:

public List<String> doSomething() {
}

通过 usingList<String>和 not ArrayList<String>,此方法可以选择使用不同的列表(例如,它可能会更改为 LinkedList ),但 API 的协定不会改变,因此所有调用代码仍然有效,即使该方法现在返回不同类型的列表。

于 2013-01-04T14:10:06.193 回答
1

在接口中定义了哪些方法是可用的,所以当一个类被写来实现一个接口时,它必须有接口中定义的方法。(它也可能有其他方法)

假设您编写了一个其他人将使用的类,并且它具有这样的方法:

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>());

他们可以自由选择适合其目的的列表类型(实现)。

于 2013-01-04T14:11:30.110 回答
1
List<Class> name = new ArrayList<Class>(#)
SuperType   ref  =     SubTypeObj

这是创建 ArrayList 的多态方式。List 是 ArrayList 的超类型。像这样创建数组列表的好处是:

  • 您可以稍后参考相同的列表来创建 LinkedList。

    名称 = 新的链表(#)

于 2013-01-04T14:07:03.663 回答
0

他的意思是你应该只使用你需要的变量类型。例如,除非您使用仅定义在的方法,否则ArrayList您应该使用List. 同样,如果您不需要任何来自List然后使用Collection等。

有两个原因:

1)它使将来更容易将实现更改为另一种类型。假设您正在使用一些使用 a 的 ORM,LazilyLoadedList那么如果您的所有代码都反对,List那么您可以轻松地将其插入。如果反对,ArrayList那么您需要更改大量方法签名并确保您不依赖于ArrayList特定方法。这是什么的一部分

2)使用 JMock 或 Mockito 等工具更容易模拟接口。

于 2013-01-04T14:10:36.133 回答
0

这应该可以帮助您了解接口是什么以及它在软件开发中的用途。

假设您需要将包裹邮寄给某人。有许多承运商选择:USPS、UPS、FedEx 等。

现在想象一下,如果有一个中央邮箱,您可以将包裹放入其中,并且所有承运人都可以从该邮箱投递。所以,你不在乎它是如何被 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);
于 2013-01-04T14:45:01.713 回答