我曾多次看到有人提到这一点,但我不清楚这是什么意思。你什么时候,为什么要这么做?
我知道接口是做什么的,但我不清楚这一点的事实使我认为我错过了正确使用它们。
如果你要这样做
IInterface classRef = new ObjectWhatever()
你可以使用任何实现IInterface的类吗?你什么时候需要这样做?我能想到的唯一一件事是,如果你有一个方法,你不确定什么对象将被传递,除了它实现IInterface。我不知道你需要多久做一次。
另外,如何编写一个方法来接受实现接口的对象呢?这可能吗?
我曾经给学生的一个具体例子是他们应该写作
List myList = new ArrayList(); // programming to the List interface
而不是
ArrayList myList = new ArrayList(); // this is bad
在一个短程序中,它们看起来完全相同,但如果在程序中继续使用myList 100次,就会开始看到区别。第一个声明确保只调用myList上由List接口定义的方法(因此没有ArrayList特定的方法)。如果您以这种方式对接口进行了编程,那么稍后您就可以确定您确实需要
List myList = new TreeList();
你只需要在这一点上修改代码。您已经知道,其余的代码不会因为更改实现而被破坏,因为您对接口进行了编程。
当您谈论方法参数和返回值时,好处甚至更明显(我认为)。举个例子:
public ArrayList doSomething(HashMap map);
该方法声明将您绑定到两个具体实现(ArrayList和HashMap)。一旦从其他代码调用该方法,对这些类型的任何更改都可能意味着您将不得不更改调用代码。最好是根据接口进行编程。
public List doSomething(Map map);
现在,不管您返回什么样的List,或者作为参数传入什么样的Map。在doSomething方法中所做的更改不会强制您更改调用代码。
前面的回答主要关注为了可扩展性和松耦合而对抽象进行编程。虽然这些都很重要,
可读性同样重要。可读性允许其他人(以及您未来的自己)以最小的努力理解代码。这就是可读性利用抽象的原因。
根据定义,抽象比实现更简单。抽象省略了细节以传达事物的本质或目的,仅此而已。
由于抽象更简单,与实现相比,我可以一次在脑海中容纳更多的抽象。
作为一名程序员(使用任何语言),我的脑海中始终有一个List的大致概念。特别是,List允许随机访问、重复元素并保持顺序。当我看到这样的声明:List myList = new ArrayList()我想,很酷,这是一个以我理解的(基本)方式使用的List;我就不用再想了
On the other hand, I do not carry around the specific implementation details of ArrayList in my head. So when I see, ArrayList myList = new ArrayList(). I think, uh-oh, this ArrayList must be used in a way that isn't covered by the List interface. Now I have to track down all the usages of this ArrayList to understand why, because otherwise I won't be able to fully understand this code. It gets even more confusing when I discover that 100% of the usages of this ArrayList do conform to the List interface. Then I'm left wondering... was there some code relying on ArrayList implementation details that got deleted? Was the programmer who instantiated it just incompetent? Is this application locked into that specific implementation in some way at runtime? A way that I don't understand?
我现在对这个应用程序感到困惑和不确定,我们所讨论的只是一个简单的List。如果这是一个忽略其接口的复杂业务对象呢?那么我的业务领域知识不足以理解代码的目的。
因此,即使当我在私有方法中严格需要List时(如果它改变了,不会破坏其他应用程序,并且我可以很容易地找到/替换IDE中的每个用法),它仍然有利于编程到抽象的可读性。因为抽象比实现细节更简单。您可以说,对抽象进行编程是遵循KISS原则的一种方式。
program to an interface is a term from the GOF book. i would not directly say it has to do with java interface but rather real interfaces. to achieve clean layer separation, you need to create some separation between systems for example: Let's say you had a concrete database you want to use, you would never "program to the database" , instead you would "program to the storage interface". Likewise you would never "program to a Web Service" but rather you would program to a "client interface". this is so you can easily swap things out.
我发现这些规则对我很有帮助:
1. 当我们有多种类型的对象时,我们使用Java接口。如果我只有一个对象,我就看不到意义了。如果某个想法至少有两种具体实现,那么我会使用Java接口。
2. 如果如上所述,您希望从外部系统(存储系统)到自己的系统(本地DB)进行解耦,那么也需要使用接口。
注意有两种方法来考虑何时使用它们。