封裝
封裝也叫作信息隱藏或者數據訪問保護。類通過暴露有限的訪問接口,授權外部僅能通過類提供的方式來訪問內部信息或者數據。它需要編程語言提供權限訪問控制語法來支持,例如 Java 中的 private、protected、public 關鍵字。封裝特性存在的意義,一方面是保護數據不被隨意修改,提高代碼的可維護性;另一方面是僅暴露有限的必要接口,提高類的易用性。
/**
* 用戶info
* 存儲用戶id,愛好
* 用戶ID是初始化中已經賦值的,不允許外部修改,只允許獲取
* 愛好屬性允許外部修改和獲取
*/
class UserInfo {
private String id;//用戶id
private String hobby;//愛好
public UserInfo() {
id = DB.getID();
}
public String getId() {
return id;
}
public String getHobby() {
return hobby;
}
public void setHobby(String hobby) {
this.hobby = hobby;
}
}
用戶id是唯一屬性,不允許外部修改,它是需要被保護的數據,所以只提供了get方法。而愛好屬性,允許外部修改,所以我們可以暴露方法對其進行修改。
當然,我們也可以使用public、protected、private等關鍵字來修飾變量和方法,達到外部安全操作內部變量的效果。
封裝保證了數據的安全性,也減少了代碼的暴露,進而提高了類的易用性。
抽象
抽象就是講如何隱藏方法的具體實現,讓使用者只需要關心方法提供了哪些功能,不需要知道這些功能是如何實現的。抽象可以通過接口類或者抽象類來實現,但也並不需要特殊的語法機制來支持。抽象存在的意義,一方面是提高代碼的可擴展性、維護性,修改實現不需要改變定義,減少代碼的改動範圍;另一方面,它也是處理複雜系統的有效手段,能有效地過濾掉不必要關注的信息。
interface IPictureHelper{
boolean savePicture();//保存照片
boolean delPicture();//刪除照片
}
class PictureHelper implements IPictureHelper{
@Override
public boolean savePicture() {
//doTask
return false;
}
@Override
public boolean delPicture() {
//doTask
return false;
}
}
在demo中,我們用一個interface類即可實現抽象。對於外部調用者來說,他們完全沒必要關注內部方法的具體實現,只需要瞭解提供的哪些方法。
其實,抽象的實現不僅僅只是interface,同時還有abstract類。不過,對於抽象的思想,如果我們仔細觀察“函數”這一語法機制,我們就能發現,“函數”包裹具體的實現邏輯,開發者在開發過程中只需要通過“函數”的命名、註釋、文檔等手段,都可以瞭解到其功能,而不必關注具體實現。這恰恰也是一種抽象的思想。
所以很多時候,我們只會講面向對象三大特性,把抽象這一特性從中移除。
繼承
繼承是用來表示類之間的 is-a 關係,分爲兩種模式:單繼承和多繼承。單繼承表示一個子類只繼承一個父類,多繼承表示一個子類可以繼承多個父類。爲了實現繼承這個特性,編程語言需要提供特殊的語法機制來支持。繼承主要是用來解決代碼複用的問題。
class BaseClass {
public String tag;
}
class Sun extends BaseClass {
}
繼承的好處是代碼複用,子類可以重用父類中的代碼。不過這也產生了弊端,過多的繼承導致了層次結構的複雜,而且父類中代碼有所修改,直接影響到了子類。所以有時候也會提倡“多組合少繼承”的思路。
多態
多態是指子類可以替換父類,在實際的代碼運行過程中,調用子類的方法實現。多態這種特性也需要編程語言提供特殊的語法機制來實現,比如繼承、接口類、duck-typing。多態可以提高代碼的擴展性和複用性,是很多設計模式、設計原則、編程技巧的代碼實現基礎。
// 父類 = 子類的實現
class BaseArray {
ArrayList<String> arrayList = new ArrayList<String>();
//父類添加value是放在數據尾部
public void add(@NotNull String value) {
if (value.equals(“”)) {
return;
}
arrayList.add(value);
}
}
class FirstArray extends BaseArray {
@Override
public void add(String value) {
if (value.equals("")) return;
//子類添加value是放在數據頭部
arrayList.add(0, value);
}
}
public class Polymorphism {
public static void main(String[] args){
BaseArray array=new FirstArray();
array.add("1");
array.add("2");
//打印 :2,1
}
}
以上代碼中,在調用add的方法時,實際是子類代替了父類的實現,執行了子類的add方法,達到了多態的特性。
我把他理解爲:父類等於子類的實現。
//接口=接口實現類
interface IPerson {
void say();
}
class Man implements IPerson {
@Override
public void say() {
System.out.println(“男的!!!”);
}
}
class Woman implements IPerson {
@Override
public void say() {
System.out.println(“女的~~~”);
}
}
class Demo {
public static void test(IPerson person) {
person.say();
}
}
public class Polymorphism {
public static void main(String[] args) {
Man man = new Man();
Demo.test(man);
Woman woman = new Woman();
Demo.test(woman);
//打印:
//男的!!!
//女的~~~
}
}
以上代碼中,我們使用interface來實現多態。Man類和Woman類都實現了IPerson接口類,而在test方法中,我們只需要知道接口類的方法。當傳入不同的實現類,調用的便是實現類的方法。
我把他理解爲:接口等於接口實現類。