OOP編程四大特性:封裝、抽象、繼承、多態

封裝

封裝也叫作信息隱藏或者數據訪問保護。類通過暴露有限的訪問接口,授權外部僅能通過類提供的方式來訪問內部信息或者數據。它需要編程語言提供權限訪問控制語法來支持,例如 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方法中,我們只需要知道接口類的方法。當傳入不同的實現類,調用的便是實現類的方法。
我把他理解爲:接口等於接口實現類。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章