我只是努力了解接口的强大功能以及如何最有效地使用它们。
到目前为止,我了解接口: 使我们能够拥有另一层抽象,分隔(由界面定义)和如何(任何有效的实现)。
鉴于只有一个实现,我只是建造一个房子(以一种特定的方式)并在这里说,它完成而不是围绕建筑计划(界面)并要求你,其他开发人员按照我的预期来构建它
到目前为止,这么好。
令我感到困惑的是,当涉及到方法参数和返回值时,为什么要优先考虑类类型的接口类型。为什么会这样?有什么好处(课堂方法的缺点)?
最让我感兴趣的是它实际上如何转化为代码。
假设我们有一种伪mathInterface
public interface pseudoMathInterface {
double getValue();
double getSquareRoot();
List<Double> getFirstHundredPrimes();
}
//...
public class mathImp implements pseudoMathInterface { }
//.. actual implementation
所以在getPrimes()方法的情况下,我会将它绑定到List,这意味着List接口的任何具体实现,而不是像ArrayList这样的概念实现!?
就方法参数而言,我将再次扩大我的机会,同时确保我可以使用我希望做的任何类型,因为它是该类型最终实现的接口合同的一部分。 !?
答案 0 :(得分:2)
假设您是Maven依赖项的创建者,这是一个具有众所周知且具有良好指定API的JAR。
如果您的方法请求ArrayList<Thing>
,则将其视为收集的,但我所拥有的只是HashSet<Thing>
,您的方法会扭曲我的方法将所有内容复制到ArrayList
中,无益;
如果你的方法声明返回一个ArrayList<Thing>
,其中(语义上)只包含一个的事物集合,并且其中的元素索引没有任何意义,那么你永远约束自己回归实际ArrayList
,即使例如该项目的未来发展过程显而易见,迫切需要一种专门针对该方法的典型用例进行优化的定制集合实现,以改善关键性能瓶颈。
您被迫进行 API更改,再次对您的客户没有任何好处,只是为了解决内部问题。与此同时,你有人编写假设ArrayList
的代码,例如通过索引迭代它(这样做会有非常轻微的性能增益,但是有早期的优化器那里的人很多。
我建议你明智地将上述两个陈述概括为一般原则,以捕捉你问题的“原因”。
答案 1 :(得分:1)
更喜欢正式参数类型的接口的一个重要原因是它不会将您绑定到特定的类层次结构。 Java仅支持单继承实现(类继承),但它支持无限继承接口(implements
)。
返回类型是一个不同的问题。一个好的经验法则是更喜欢最常用的可能参数类型,以及最具体的可能返回类型。 “最普遍的可能”非常简单,它明确地与正式参数的首选接口类型对齐。然而,“最具体可能”的返回类型比较棘手,因为它取决于“可能”的含义。
使用接口类型作为方法的声明返回类型的一个原因是允许您返回非公共类的实例。另一种方法是保持灵活性,以便在不破坏相关代码的情况下更改返回的特定类型。另一个是允许不同的实现返回不同的类型。这只是我的头脑。
答案 2 :(得分:0)
所以在getPrimes()方法的情况下,我会将它绑定到List,这意味着List接口的任何具体实现,而不是像ArrayList这样的概念实现!?
是的,这允许该方法稍后更改它返回的List类型,而不会破坏使用该方法的客户端代码。
除了能够在不破坏代码的情况下更改实际传递给/返回的对象的能力之外,有时最好使用接口类型作为参数/返回类型来降低可用字段和方法的可见性。这将降低随后使用该接口类型对象的代码的整体复杂性。