接口和抽象類的區別
接口
- 接口是對行爲的抽象,它是抽象方法的集合,利用接口可以達到
API
定義和實現分離的目的。 - 有一類沒有任何方法的接口用作標誌,比如
Serializable
接口就表示這個類可以被序列化 - 不能實例化;
- 不能包含任何非常量成員,任何
field
都是隱含着public static final
的意義; - 沒有非靜態方法實現,也就是說要麼是抽象方法,要麼是靜態方法。
Java
類實現interface
使用implements
關鍵詞Java 8
以後增加了默認方法。在方法簽名前加上default
。它可以爲接口添加新的方法,而不會破壞已有的接口的實現。Java 8
新增了函數式接口,接口內只含有一個抽象方法。通常使用@FunctionalInterface Annotation
。Lambda
表達式只能用於函數式接口
抽象類
- 抽象類是不能實例化的類,用
abstract
關鍵字修飾class
, - 其目的主要是代碼重用。除了不能實例化,形式上和一般的
Java
類並沒有太大區別,可以有一個或者多個抽象方法,也可以沒有抽象方法。 - 抽象類大多用於抽取相關
Java
類的共用方法實現或者是共同成員變量,然後通過繼承的方式達到代碼複用的目的。 - 繼承
abstract class
則是使用extends
關鍵詞
面向對象基礎
基本要素
最後一個示例實在讓我有些驚訝,從沒注意過這些東西,就將他們全部複製下來了
OOP 原則在面試題目中的分析
我在以往面試中發現,即使是有多年編程經驗的工程師,也還沒有真正掌握面向對象設計的基本的原則,如開關原則(Open-Close)。看看下面這段代碼,改編自朋友圈盛傳的某偉大公司產品代碼,你覺得可以利用面向對象設計原則如何改進?
public class VIPCenter {
void serviceVIP(T extend User user>) {
if (user instanceof SlumDogVIP) {
// 窮X VIP,活動搶的那種
// do somthing
} else if(user instanceof RealVIP) {
// do somthing
}
// ...
}
這段代碼的一個問題是,業務邏輯集中在一起,當出現新的用戶類型時,比如,大數據發現了我們是肥羊,需要去收穫一下, 這就需要直接去修改服務方法代碼實現,這可能會意外影響不相關的某個用戶類型邏輯。利用開關原則,我們可以嘗試改造爲下面的代碼:
public class VIPCenter {
private Map<User.TYPE, ServiceProvider> providers;
void serviceVIP(T extend User user) {
providers.get(user.getType()).service(user);
}
}
interface ServiceProvider{
void service(T extend User user) ;
}
class SlumDogVIPServiceProvider implements ServiceProvider{
void service(T extend User user){
// do somthing
}
}
class RealVIPServiceProvider implements ServiceProvider{
void service(T extend User user) {
// do something
}
}
上面的示例,將不同對象分類的服務方法進行抽象,把業務邏輯的緊耦合關係拆開,實現代碼的隔離保證了方便的擴展。