扩展Initializing an Interface?中提出的问题,我们确实实例化了一个接口,同时用实现的类初始化它。
我的问题是为什么首先,我们用接口实例化它?为什么我不能用实现的类直接实例化它? 例如。 :
Doc mydoc = new SimpleDoc();
Doc是接口,SimpleDoc正在实现它。 有什么问题 SimpleDoc mydoc = new SimpleDoc(); 这会失败吗?
答案 0 :(得分:0)
如果在客户端代码中使用接口而不是实现类,则可以在不更改客户端代码的情况下更改实现。
答案 1 :(得分:0)
我们称之为虚拟方法调用或后期绑定
让我们看一个例子。
public interface Vegetarian{}
public class Animal{}
public class Deer extends Animal implements Vegetarian{}
现在,Deer类被认为是多态,因为它具有多重继承。以下示例如下:
A Deer IS-A Animal
A Deer IS-A Vegetarian
A Deer IS-A Deer
A Deer IS-A Object
当我们将引用变量事实应用于Deer对象引用时,以下声明是合法的:
Deer d = new Deer();
Animal a = d;
Vegetarian v = d;
Object o = d
所有引用变量d,a,v,o
都引用堆中的相同Deer
对象。
答案 2 :(得分:0)
如果你写:
SimpleDoc mydoc = new SimpleDoc();
所有进一步的代码可能依赖于实现类SimpleDoc
公开的细节。但如果你写:
Doc mydoc = new SimpleDoc();
进一步的代码我只依赖于Doc
公开的方面,这使得代码在你决定将来编写时甚至可以工作:
Doc mydoc = new ComplexDoc();
差异的一个很好的例子是List
,它至少有两个实现:
ArrayList
LinkedList
如果你写:
List list = new ArrayList();
您可以稍后用以下内容替换它:
List list = new LinkedList();
不破坏依赖于变量list
的代码(假设您没有使用强制转换或反射来访问list
的实现特定功能)。
答案 3 :(得分:0)
在系统中依赖抽象类型(接口或抽象类)通常是一种好习惯。
在你的例子中,你确实可以写:
SimpleDoc mydoc = new SimpleDoc()
但问题是使用mydoc
的代码将取决于具体类型SimpleDoc
。这不一定是一个问题,但是,假设您创建Doc
的新实现,比如说ComplexDoc
。
您将声明更改为:
ComplexDoc mydoc = new ComplexDoc();
现在,您传递mydoc
的所有场所方法也必须更改。
但是,如果您首先使用Doc
,则只需进行一次更改:
Doc mydoc = ComplexDoc();
当您使用Collections API时,此功能特别有用,通常可以切换另一个实现或在测试用例中使用Mocking。