什么是“界面”以及如何编程“反对”它?

时间:2013-01-04 14:03:33

标签: java interface

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

昨天有人告诉我这样的事情是不好的做法,我应该“反对界面”编程,如下:

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

他是什么意思?

8 个答案:

答案 0 :(得分:3)

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

答案 1 :(得分:3)

没有必要透露您正在使用的List的确切实现。

您可以使用的唯一方法是界面中的方法。从技术上讲,它并不重要,但它是一个很好的习惯。代码更清晰,更易于维护。

答案 2 :(得分:2)

该代码段中的“界面”List是一个比ArrayList更抽象的类。

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

通过使用界面声明namename的用户不必知道列表name实际上是哪种类型,以及您是否决定使用其他类型以后您可以在不需要更改代码中的大量位置的情况下使用List。

答案 3 :(得分:1)

List<Class> name = new ArrayList<Class>(#)
SuperType   ref  =     SubTypeObj

这是创建ArrayList的多态方式。 List是一个超类型的ArrayList。 创建这样的arraylist的好处是:

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

    name = new LinkedList(#)

答案 4 :(得分:1)

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

public List<String> doSomething() {
}

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

答案 5 :(得分:1)

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

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

答案 6 :(得分:0)

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

这有两个原因:

1)将来更容易将实现更改为其他类型。假设您正在使用一些使用LazilyLoadedList的ORM,如果您的所有代码都针对List,那么您可以毫不费力地插入它。如果它是针对ArrayList,那么您需要更改许多方法签名,并确保您不依赖于ArrayList特定方法。这是

的一部分

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

答案 7 :(得分: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);