面向對象編程

面向過程&面向對象

  • 面向對象編程思想
    • 步驟清晰簡單,第一步做什麼,第二部做什麼…
    • 面向過程適合處理一些較為簡單的問題
  • 面向對象編程
    • 物以類聚,分類的思維模式。思考問題首先會解決問題需要那些分類,然後對這些分類進行單獨思考。最後,才對某個分類下的細節進行面向過程的思索。
    • 面向對象適合處理複雜的問題,適合處理需要多人協作的問題。
  • 對於描述複雜的事物,為了從宏觀上把握,從整體上合理分析,我們需要使用面向對象的思路來分析整個系統。但是,具體到圍觀操作,仍然需要面向過程的思路去處理。

什麼是面向對象

  • 面向對象編程(Object-Oriented Programming,OOP)
  • 面向對象編程的本質就是:以類的方式組織程式碼,以對象的組織(封裝)數據。
  • 抽象
  • 三大特性:
    • 封裝
    • 繼承
    • 多態
  • 從認識論角度考慮是先有對象後有類。對象,是具體的事物。類,是抽象的,是對對向的抽象
  • 從程式碼運行角度考慮是現有類後有對象。類是對象的模板。

方法的定義

  • 修飾符
  • 返回類型
  • break和return的區別
  • 方法名
  • 參數列表
  • 異常輸出

方法的調用

  • 靜態方法(static)
    • 和類一起載入的,因此可以不用實例化就可以調用
  • 非靜態方法
    • 類實例化之後才存在
  • 形參和參數
  • 值傳遞和引用傳遞
  • this關鍵字

類與對象的關係

  • 類是一種抽象的數據類型,它是對某一事物整體描述/定義,但是不能代表某一個具體事務。
  • 對象是抽象概念的具體實例。

類的創建與初始化對象

  • 使用new關鍵字創建對象

  • 使用new關鍵字創建的時候,除了分配記憶體空間之外,還會給創建好的對象進行默認的初始化以及類中構造器的調用。

  • 類中的構造器也成為構造方法,是在進行創建的時候必須要調用的。並且構造器有一下兩種特點:

    1. 必須和類的名字相同。
    2. 必須沒有返回類型,也不能寫void。

構造器

  • 作用:
    1. new本質是在調用構造方法。
    2. 初始化對象的值。
  • 注意:在定義了一個有參構造只有,如果要使用無參構造,需要再定義一個無參構造。
  • IDEA快捷鍵:ALT+INSERT或者右鍵–>generate
  • 子類的構造器默認調用父類的構造器,即有一行隱藏程式碼super();
  • 構造器是必須掌握的重點

封裝

屬性私有,get/set

  • 該露的露,該藏的藏。

    • 我們程式設計要追求「高內聚,低耦合」。高內聚就類的內部數據操作細節自己完成,不許外部干涉;低耦合:僅暴露少量的方法給外部使用。
  • 封裝(數據的隱藏)

    • 通常,應該禁止直接訪問一個對象中數據的實際表示,而應該通過操作介面來訪問,這成為資訊隱藏。
  • 優點:

    1. 提高程式的安全性,保護數據
    2. 隱藏程式碼的實現細節。
    3. 統一介面。
    4. 系統可維護性增加了。
    public class Student {
        //屬性私有
        private String name;
        private char sex;
        private int id;
        //提供一些可以操作這個屬性的方法。
        //提供一些public的get、set方法
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public char getSex() {
            return sex;
        }
    
        public void setSex(char sex) {
            this.sex = sex;
        }
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    }
    

繼承

  • 繼承的本質是對某一批類的抽象,從而實現對現實世界更好的建模。
  • extends的意思是「擴展」,子類是父類的擴展。
  • Java中只有單繼承,沒有多繼承!
    • 一個兒子只能由一個爸爸,一個爸爸可以有多個兒子。
  • 繼承是類和類之間的一種關係。除此之外,類和類之間的關係還有依賴、組合、聚合等。
  • 繼承關係的兩個類,一個為子類(派生類),一個為父類(基類)。子類繼承父類,使用關鍵字extends來表示。
  • 子類和父類之間,從意義上應該具有「is a」的關係
    • 子類繼承了父類,就會有父類的全部方法。注意要是父類的public和protected方法。
    • 私有的(private)東西無法被繼承。
    • 優先順序public、protected、default、private。
  • object類
    • idea快捷鍵:ctrl + h 打開繼承樹。
    • 在Java中,所有的類都默認直接或間接繼承object類。
  • super
    • 子類的構造器默認調用父類的構造器,即有一行隱藏程式碼super();
    • 調用構造器一定要在第一行。
    • 如果父類只有含參構造,那麼子類就無法寫無參構造。除非子類用super(參數)來實現無參。
    • 注意
      • super調用父類的構造方法,必須在構造方法的第一個
      • super必須只能出現在子類的方法或者構造方法中。
      • super和this不能同時調用構造方法(調用構造方法需要在第一行,這兩一起調用衝突)
    • vs this
      • 代表的對象不同
        • this:這個對象本身
        • super :代表父類對象的應用
      • 前提
        • this:沒有繼承也可以使用
        • super:只能在繼承條件才可以使用
      • 構造方法
        • this():本類的構造方法。
        • super():父類的構造方法。
  • 方法重寫:重點–>多態
    • @override注釋,重寫
    • 重寫需要有繼承關係,子類重寫父類的方法。
    • 參數列表必須相同
    • 修飾符:範圍可以擴大:public->protected->default->private
    • 拋出的異常:範圍可以被縮小,但不能擴大:classNotFoundException->Exception(大)這樣是不行的。
    • 子類和父類的方法一致,方法體不同。
    • 重寫都是方法的重寫,與屬性無關。
    • 私有的方法無法重寫。
    • 只有非靜態的方法才能重寫。
    • 靜態方法:方法的調用只和左邊定義的數據類型有關。
    • 為什麼需要重寫?
      • 父類的功能,子類不一定需要,或者不一定滿足!
    • idea快捷鍵:alt + inter:override

多態

  • 動態編譯:類型。

  • 即同一方法可以根據發送對象的不同而採用多種不同的行為方式。

  • 一個對象的實際類型是確定的,但可以指向對象的引用的類型有很多

    //一個對象的實際類型是確定的
    new Student();
    new Person();
    //可以指向的引用類型就不確定了:父類引用指向子類
    Student s1 = new Student();
    Person s2 = new Student();
    Obeject s3 = new Student();
    
  • 對象能執行哪些方法,主要看對象左邊的類型,和右邊的關係不大。

  • 子類重寫了父類的方法,執行子類的方法。

  • 多態注意事項

    • 多態是方法的多態,屬性沒有多態
    • 子類和父類,有聯繫,類型轉換異常!
    • 存在條件:繼承關係,方法需要重寫,父類引用指向子類對象!Father f1 = new Son()
  • 不可多態的:

    • static 方法,屬於類,它不屬於實例
    • final常量
    • private方法
  • instanceof (類型轉換)引用類型,判斷一個對象是什麼類型。

類型轉換

  • 父–>子

    • 將父類型強轉成子類型,就可以使用子類的方法了。
    • 子轉父不需要強轉,父轉子需要,有可能會丟失一些方法。
  • 高–>低

static方法

package demo;
//static
public class Student {
    private static int age;//靜態變數
    private double score;//非靜態變數
    public static void go(){

    }
    public void run(){

    }
    public static void main(String[] args) {
        Student student = new Student();
        System.out.println(Student.age);
        //System.out.println(Student.score);報錯
        System.out.println(student.score);
        go();
        Student.go();
        //run();報錯;
        //Student.run();報錯;
        new Student().run();
    }

}
package demo;
import static java.lang.Math.random;
public class Person {
    {
        System.out.println("匿名程式碼塊(每次聲明類的時候執行)");
    }
    static {
        System.out.println("靜態程式碼塊(只執行一次)");
    }
    public Person(){
        System.out.println("構造體");
    }
    public static void main(String[] args) {
        //Person person = new Person();
        /*
         * 靜態程式碼塊(只執行一次)
         * 匿名程式碼塊(每次聲明類的時候執行)
         * 構造體
         */
        Person person1 = new Person();
        Person person2 = new Person();
        /*
         * 靜態程式碼塊(只執行一次)
         * 匿名程式碼塊(每次聲明類的時候執行)
         * 構造體
         * 匿名程式碼塊(每次聲明類的時候執行)
         * 構造體
         */
    }
}

package demo;
import java.lang.Math.*;
//靜態導入包
import static java.lang.Math.random;

public class Test {
    public static void main(String[] args) {
        System.out.println(random());
        //如果,沒有靜態導入包
        //System.out.println(Math.random());
    }
}

抽象類

  • abstract修飾符可以用來修飾方法也可以用來修飾類,如果修飾方法,那麼方法就是抽象方法,如果修飾類,那麼類就是抽象類。
  • 抽象類中可以沒有抽象方法,但是有抽象方法的類一定時抽象類。
  • 抽象類,不能使用new關鍵字來創建對象,用來讓子類繼承的,是一個約束,只能讓子類來實現。
  • 抽象方法,只有方法的聲明,沒有方法的實現,用來讓子類繼承。
  • 子類繼承抽象類,那麼就必須要實現抽象類沒有實現的抽象方法,否則該子類也要聲明為抽象類。(抽象的抽象:約束~)
  • 局限性:類只能單繼承,無法多繼承。

介面

  • 普通類:只有具體實現。

  • 抽象類:具體實現和規範(抽象方法)都有!

  • 介面:只有規範!自己無法寫實現方法,專業的約束!約束和實現分離:面向介面編程。

  • 介面就是規範,定義的是一組規則,體現了現實世界中「如果你是…則必須能…」的思想。

  • 介面的本質是契約,就像我們人間的法律一樣,訂製好後大家都遵守。

  • 面向對象的精髓,是對對象的抽象,最能體現這一點的就是介面。為什麼我們討論設計模式都只針對具備了抽象能力的語言,就是因為設計模式所研究的,實際上就是如何合理的去抽象。

  • 通過implement實現。

    聲明類的關鍵字是class,聲明介面的關鍵字是interface

內部類

  • 內部類就是在一個類的內部定義一個類,比如,A類中定義一個B類,那麼B類相對A類來說成為內部類,而A類相對B類來說就是外部類了。

    1. 成員內部類

    2. 靜態內部類

    3. 局部內部類

      • 在局部方法中的內部類。
    4. 匿名內部類

      • 沒有名字初始化類,不用將實例保存到變數中。

        new Apple().eat();