通过接口引用对象。总是?

时间:2013-08-13 23:13:54

标签: java effective-java

来自有效java的剪切代码,这里我们使用List来遵循通过其接口引用对象的良好实践。

// Good - uses interface as type
List<Subscriber> subscribers = new Vector<Subscriber>();

假设我们有一个car接口,2wheel4wheel是具体的子类。 甚至建议(似乎很肯定)构建“car”类型列表?

List<Car> car = new Vector<2wheel>();

而不是

List<2wheel> car = new Vector<2wheel>();

2 个答案:

答案 0 :(得分:3)

我同意这本书。始终使用接口类型。我在2wheel中使用4wheelList实现的唯一方法是,如果它们包含需要调用的不在接口上的特定方法。

例如:

public interface Car{
   public void drive();
}

public class 2wheel implements Car{
   public void drive(){
      //implementation
   }
}


public class 4wheel implements Car{
   public void drive(){
      //implementation
   }

   public void initiate4WheelDrive(){
      //implementation
   }
}

如果您有一个List且代码使用了调用initiate4WheelDrive方法所需的列表,那么您必须使用具体实现。这通常由调用代码决定,但如果可能,请坚持使用接口,以便您可以轻松交换实现。

另一个注释,名称2wheel在Java中是无效的名称,因为类和接口名称不能以数字开头。

答案 1 :(得分:0)

接口特定于某个类型,并且许多类可以通过共享相同类型来共享相似(或相同)的行为。

如果接口表示实现类的主要功能,用途或行为,则使用接口名称引用该类型的实例是很有意义的。集合类和JDBC RowSet类就是很好的例子。 CachedRowSet实例的一个强烈定义的特性是它是一个RowSet,由RowSet接口的契约定义。

但是有些类,它们实现的接口提供附件功能或行为。在这些情况下,界面的合同不是该类的存在理由......在这里,我不同意布洛赫先生的maxxim,即每个接口都应该成为你引用所有实例的类型。

为了使这更具体,实现Comparable实例化为可比较的类的次数是多少?还是克隆人?当然,有时使用这些“较小的接口”作为某些方法参数的类型是有意义的......但这与“始终将对象称为接口定义的类型的实例”不同。

TL; DR:接口应该用作对象类型的规则是一个很好的规则,主要是当接口具有明确的合同并且合同定义实现类的主要功能,行为或目的时。 / p>