Java面向對象三大特徵的理解

面向對象三大特徵的理解

初始理解

其實這些知識很早就有接觸,而且一些概念也牢記於心了。自己敘述面向對象的特徵會是這樣的:
面向對象的三大特徵是封裝、繼承和多態。封裝是對代碼的封裝以實現迪內聚高耦合的設計,使代碼更安全且具有良好的擴展性。繼承是父類產生子類的過程,子類可以使用父類的非私有的屬性和方法。多態是一個對象在不同時刻可以表現出不同狀態的現象。外加Animal和Cat的例子。
這一段時間敲了不少的Java代碼,在敲代碼的過程中想了無數次的面向對象這幾個概念,對他們有了更深的瞭解,在這裏分享一下。

封裝

封裝確實是對代碼的封裝,但是隻是這樣理解卻又太膚淺了,至少結合Java來思考一下里面的封裝嘛。
不知道大家有沒有想過我們在寫JavaBean的時候爲什麼要將屬性的權限修飾爲private,其實是爲了使我們的代碼更安全。分析如下:

public class Cat {
    //這裏通過private修飾屬性,外界訪問屬性需要通過getter和setter方法
    private String name;
    private int age;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    //假設我們設置age,如果用戶惡意將age設置爲100
    //衆所周知,impossible,因此我們可以通過setter方法進行if判斷然後再賦值
    public void setAge(int age) {
        this.age = age;
    }
}
我們可以考慮一下如果沒有setter方法的判斷,我們將該類的屬性設置爲public呢?那麼用戶的惡意輸入,怎樣規避呢?
總之:private是封裝的一種體現。

封裝還有其他的方法:爲了提高代碼的複用性可以將公共邏輯抽取成方法,將公共屬性抽取成類。例如我們在不同的位置用到了相同的for循環,在idea中我們就可以選中相同的for循環部分,點擊快捷鍵 ctrl + alt + m 將其抽取爲方法。

繼承

繼承是面向對象的三大特徵之一,過程就是使子類獲得父類的屬性和方法。
這個過程較容易理解,關鍵字是extends,如果我們定義的類沒有顯式繼承某個類,系統默認爲我們繼承Objects。繼承是我們代碼的coding量變少了,提高了代碼的複用性。
這裏更深的體會是繼承提高了代碼的維護性。主要表現就是如果方法的代碼需要修改,某些情況下我們只需要修改一處就可以實現。
但是這裏還有一點沒有想通的繼承肯定會增加代碼的耦合性,我們爲什麼還要這樣誇大繼承呢?我有這種疑問就是陷入了一個思維的誤區,可以看這篇文章來解疑:爲耦合辯護,爲繼承伸冤

多態

多態的三個必要條件是:

  1. 有繼承或實現關係
  2. 有方法的重寫
  3. 父類引用指向子類對象
class Fu {
    int num = 10;
    public void method(){
        System.out.println("Fu.. method");
    }
}
class Zi extends Fu {
    int num = 20;
    public void method(){
        System.out.println("Zi.. method");
    }
}
public class Test2Polymorpic {
    public static void main(String[] args) {
        Fu f = new Zi();
        System.out.println(f.num);
        f.method();
    }
}

關於爲什麼訪問成員變量和成員方法的會分別get父類和子類的值和方法,這裏有講解。從虛擬機角度看Java多態->(重寫override)的實現原理

  1. 好處:提高程序的擴展性。定義方法時候,使用父類型作爲參數,在使用的時候,使用具體的子類型參與操作
  2. 弊端:不能使用子類的特有成員
    解決弊端可以通過向下轉型:格式爲子類型 對象名 = (子類型)父類引用;
class Fu {
    public void show(){
        System.out.println("Fu..show...");
    }
}
class Zi extends Fu {
    @Override
    public void show() {
        System.out.println("Zi..show...");
    }
    public void method(){
        System.out.println("我是子類特有的方法, method");
    }
}
public class Test {
    public static void main(String[] args) {
        //向上轉型 : 父類引用指向子類對象
        Fu f = new Zi();
        f.show();
        // 多態的弊端: 不能調用子類特有的成員
        // f.method();
        //解決方法:
        // A: 直接創建子類對象
        // B: 向下轉型
        //向下轉型 : 從父類類型, 轉換回子類類型
        Zi z = (Zi) f;
        z.method();
    }
}

如果被轉的引用類型變量,對應的實際類型和目標類型不是同一種類型,那麼在轉換的時候就會出現ClassCastException,可以使用instanceOf來解決。

abstract class Animal {
    public abstract void eat();
}

class Dog extends Animal {
    public void eat() {
        System.out.println("狗喫肉");
    }

    public void watchHome(){
        System.out.println("看家");
    }
}

class Cat extends Animal {
    public void eat() {
        System.out.println("貓喫魚");
    }
}

public class Test4Polymorpic {
    public static void main(String[] args) {
        useAnimal(new Dog());
        useAnimal(new Cat());
    }

    public static void useAnimal(Animal a){
        a.eat();
        // 判斷a變量記錄的類型, 是否是Dog
        if(a instanceof Dog){
            Dog dog = (Dog) a;
            dog.watchHome();
        }
    }

}

最後再來一張圖體會一下多態的強大:::::
equals的參數可以是任意對象類型,這是多態的一種應用

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