来自有效java的剪切代码,这里我们使用List
来遵循通过其接口引用对象的良好实践。
// Good - uses interface as type
List<Subscriber> subscribers = new Vector<Subscriber>();
假设我们有一个car
接口,2wheel
和4wheel
是具体的子类。
甚至建议(似乎很肯定)构建“car”类型列表?
List<Car> car = new Vector<2wheel>();
而不是
List<2wheel> car = new Vector<2wheel>();
答案 0 :(得分:3)
我同意这本书。始终使用接口类型。我在2wheel
中使用4wheel
或List
实现的唯一方法是,如果它们包含需要调用的不在接口上的特定方法。
例如:
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>