我在考虑编程接口而不是具体的类,但我有一个疑问:是否任何接口方法都能够保存对具体类的引用?
假设以下情况:
1)
public interface AbsType1 {
public boolean method1(int a); // it's ok, only primitive types here
}
2)
public interface AbsType2 {
public boolean method2(MyClass a); // I think I have some coupling here
}
我应该在这里选择不同的设计以避免后者吗? e.g。
public interface MyInterface {} // yes, this is empty
public classe MyClass implements MyInterface {
// basically identical to the previous "MyClass"
}
public interface AbsType2 {
public boolean method2(MyInterface a); // this is better (as long as the
// interface is really stable)
}
但仍有一些东西不能说服我......虽然我看到其他人这样做,但我觉得对于宣布一个空接口感到不舒服。 也许和抽象类在这里会更好用吗?
我有点困惑。
修改
好的,我会通过举个例子来尝试更具体。假设我正在设计ShopCart,我当然希望在购物车中添加商品:
public interface ShopCart {
public void addArticle(Article a);
}
现在,如果文章是一个具体的类,如果它的实现随着时间的推移而变化怎么办?这就是为什么我可以想到把它变成一个接口,但是再一次,它可能不适合至少在语义层面,因为接口应该指定行为而文章没有(或几乎没有......)我猜它是一种实体类)。
所以,我现在可能最终得出的结论是,在这种情况下将文章作为抽象类是最好的......你怎么看待它?
答案 0 :(得分:2)
我会使用接口,因为组合比继承好得多。 “任何接口方法都应该能够保存对具体类的引用吗?”,为什么它不应该?包中的某些类是耦合的,这是事实和常用技术。当您在界面中标记此关系时,您会看到哪些类依赖于您的实现。依赖关系或组合关系不是继承,所以我会避免抽象类。
答案 1 :(得分:1)
在我看来,Interfaces
对于实施可能不同的所有类型都适用。但是如果你定义了一个引入新类型的module
,那么它并不打算有替代实现,那么首先不需要将它定义为Interface
。在我看来,这通常会过度设计。它取决于问题领域,通常在支持测试或AOP编织的方式上。
例如,考虑一个2D问题域,您需要将Location
建模为一种类型。如果Location
始终由x
和y
坐标表示,则可以将其作为Class
提供。但是,如果您不知道Location
可能具有哪些属性(GPS数据,x,y,z坐标等),但您依赖某些行为,例如distance()
,则应将其建模为接口代替。
答案 2 :(得分:1)
如果AbsType
中没有MyClass
可以访问的公共方法,那么空接口可能不是一个好方法。
静态方法没有接口声明(契约),否则可能在这里有意义。
因此,如果AbsType
不会使用MyClass
/ MyInterface
中的任何方法,那么我认为它基本上只是为了其他目的而存储类对象。在这种情况下,请考虑使用泛型来明确您希望如何使用AbsType
而不与客户端代码紧密耦合,例如
public class AbsType3<C extends Class<?>> {
public boolean method3(T classType) {...}
}
然后,如果需要,可以通过将<C extends Class<?>>
类型参数替换为可能也是接口的其他内容来限制类的类型,例如
<C extends Class<Collection<?>>>
。
空接口有点像类的布尔标志:一个类实现接口(true)或不实现(false)。如果有的话,应该使用这些标记接口来传达关于如何使用(或不使用)类的重要声明,例如,请参阅Serializable
。