与使用抽象类相比,使用接口的优点包括:
1.类更容易声明执行新的接口
2.接口更容易定义mixin,如同一个类可以实现Comparable、Iterable接口。在排序时,此类可视为Comparable类型,在迭代时,此类可视为Iterable类型
3.接口允许定义非层次化的类型框架,如一个人可以同时为歌手和作曲家,那么可让Person类同时实现Singer和SongWriter接口,而Singer和SongWriter接口直接没有任何层次关系
4.接口可提供更安全和更强大的功能,如帮助实现Wrapper
使用接口的缺点:
1.直接继承抽象类比实现接口更简单
2.一旦接口被发布并且被广泛实现,后期更改接口几乎是不可能的(可能很多实现类都需要进行修改)
使用接口建议:
1.在发布接口前进行广泛的测试和讨论
2.接口仅用于定义类型,不要用于定义常量。如以下代码可能给使用者造成疑惑,并且不能避免使用者实现此接口:
注:可使用枚举,静态工具类提供常量
//never do this
public interface BadInterface {
static final String C1="C1";
static final String C2="C2";
}
3.在发布接口时,建议同时提供简单实现类或骨架实现类(skeleton),如以下接口:
public interface IContainer {
void add(String e);
void remove(String e);
}
可提供一个简单实现类:
public class SimpleContainer implements IContainer {
private List<String> list=new ArrayList<String>();
public void add(String e) {
list.add(e);
}
public void remove(String e) {
list.remove(e);
}
}
也可提供一个抽象的骨架实现类:
public abstract class AbstractContainer implements IContainer {
public abstract void add(String e) ;
public abstract void remove(String e) ;
//此处可覆盖实现equals(),hashCode()等方法
}
在使用上,可直接继承骨架实现类、使用Wrapper进行包装,或者提供工具类方法,如下:
public static IContainer getContainer(final String[] strs){
if(strs==null||strs.length==0)return null;
final List<String> list=new ArrayList<String>();
for(String str:strs)list.add(str);
return new AbstractContainer() {
@Override
public void remove(String e) {
list.remove(e);
}
@Override
public void add(String e) {
list.add(e);
}
};
}