我已经看到,如果我有名为interfaceABC的接口。
示例:
public class ABController extends AbstractCOntroller {
private interfaceABC inter;
我很困惑,为什么我们从接口创建对象而不是从实现它的类。
答案 0 :(得分:2)
我们还没有制作一个对象,我们已经制作了参考。
通过使用对接口的引用而不是具体类,我们可以自由地交换接口的不同实现,而不需要更改此代码。这改善了封装,并且还有利于例如封装。测试(因为我们可以使用mock objects)。另请参阅dependency injection。
答案 1 :(得分:2)
private interfaceABC inter;
我很困惑,为什么我们从接口制作对象而不是从实现它的类
我们尚未创建对象/实例 尚未 。我们只是声明了一个变量来保存它。我们不从接口创建对象(您必须使用具体类来执行此操作),但我们通常会使用接口类型而不是实际的具体类来进行变量声明,方法参数类型和方法返回类型。
以此为例:
List<Example> examples = new ArrayList<Example>();
...
public List<Example> getExamples() { return examples; }
在这里使用接口List
而不是具体的类ArrayList
遵循一个常见的最佳实践:尽可能使用接口而不是具体类,例如在变量声明,参数类型和方法返回类型中。这被认为是最佳做法的原因是:
使用接口进行声明和返回类型会隐藏实现细节,以便将来更容易修改。例如,我们可能会发现代码使用LinkedList
而非ArrayList
更有效。我们现在可以在一个地方轻松地进行此更改,就像实例化列表一样。这种做法对于方法参数类型和方法返回类型尤为关键,因此该类的外部用户不会看到您的类的此实现细节,并且可以自由地更改它而不会影响其代码。
通过使用界面,未来的维护者可能更清楚这个类需要某种List
,但它并不特别需要ArrayList
。如果此类依赖于某些ArrayList
特定属性,即它需要使用ArrayList
方法,那么使用ArrayList<Example> examples = ...
代替List<Example> examples = ...
可能会暗示此代码依赖特定于ArrayList
。
它可以简化测试/模拟以使用更抽象的List
而不是使用具体的类ArrayList
。
答案 2 :(得分:1)
这实际上非常有用。以我们使用列表为例。
public class A {
private List<String> list;
public A(List<String> list) {
this.list = list;
}
}
这允许类A
处理list
接口定义的所有操作。构建A
的类现在可以提供任何实现而无需更改类A
的代码,从而促进encapsulation,代码重用,测试等。例如:< / p>
new A(new ArrayList<String>());
答案 3 :(得分:1)
对于私有领域来说,这并不重要,因为这无论如何都是一个实现细节。许多人原则上仍会在任何地方使用界面。
另一方面,protected
字段(当然还有公共方法的参数)构成了一个API,通过使用接口变得更加灵活,因为它允许子类/客户端选择他们想要的实现类使用,甚至是他们自己提供的类,甚至在创建API时都不存在。
当然,如果你有一个设置私有字段的公共set方法或构造函数,那么你也必须使用该字段的接口类型。
答案 4 :(得分:1)
想象一下,商店里有一个礼品包装摊位,里面有一台可以包装任何盒子的机器。
这台机器的设计和制造都是为了包装一个长方形的盒子,无论盒子里有巧克力还是玩具车都没关系。如果它很重要,机器显然会有缺陷。
但是,即使在你到达那个摊位之前,你必须购买那个礼物:所以收银员首先扫描条形码。条形码扫描器是另一个相同原理的例子:它会扫描任何东西,只要它上面有可识别的条形码。只扫描报纸的条形码扫描仪将毫无用处。
这些观察导致了软件设计中封装的概念,当一个类仅通过接口引用一个对象而不是它的具体类时,你可以看到它的实际效果。