刚看到这两个词,很多人估计都会有一种选择恐惧症,其实,如果真的稍微了解了一下两个的不同之处以后,就不会有那么难的抉择了。
语法上
从语法上来看,abstract的可以拥有自己的属性和自己的非抽象方法,同时,子类可以覆盖掉父类的一些属性的值。interface只能含有static final的属性和抽象的方法。所以从语法上来看的话 interface其实算一种特殊的abstract。另外,abstract中的方法可以有自己默认的一些行为,但是interface中则没有。
设计上
从设计上来看,abstract与子类其实是一种"is-a"的关系,但是interface则是“like-a”的关系;interface更多的表达的是一种约束力,不是深层次的父子关系。
例:
如果我们要设计一款开关,它有两个基本功能,开和关,用abstract和interface的做法:
abstract class Switch{
abstract void open();
abstract void close();
}
interface Switch{
void open();
void close();
}
现在看,貌似这两个都可以,但是现在我们的客户要求说,现在的开关需要一个扩展功能,就是发亮。那你会怎么做的,一般人想到的基本想法就是:
abstract class Switch{
abstract void open();
abstract void close();
abstract void shine();
}
interface Switch{
void open();
void close();
void shine();
}
然后再用子类去继承或者实现上述两个。其实这样操作本身就违背了ISP原则,你将开关的基本功能给扩展了,等以后如果程序只需要开关的基本功能的时候,你会发现维护好麻烦。所以需要改进,改进的方法你会想到三个,一个是用两个abstract来做;一个是两个interface;最后一个是一个abstract,一个interface。我们一个一个来讨论:
首先是两个abstract,因为java的语法机制不允许两个entends,所以直接pass;
接下来是两个interface,如果使用两个interface,你会觉得很纠结,这个东西到底是开关呢还是灯,因为一个中定义着开和关,一个中定义着发亮,所以这里其实需要搞清楚的是你的东西到底是一个怎么样的东西,认清楚这个东西的本质。
最后一种情况是一个abstract,一个interface
abstract class Switch{
abstract void open();
abstract void close();
}
interface Switch{
void shine();
}
这样一看,咦,对了,我要的东西是一个开关,但是它有个扩展功能是发光,合情合理,又满足ISP原则,所以对于这一类问题的选择,我们需要看重的是东西的本质到底是什么。
讲了那么多,也许有些地方讲的不是很清楚或者不对的地方,请私信我,因为我也是刚从新手过来。
学无止境。共勉。