Java基礎-抽象類,接口,多態

第一小節 抽象類

1.抽象類格式和概念

    //有抽象方法的類,一定是抽象類
    abstract class Demo1{

        //被`abstract`修飾的都是抽象方法
        public abstract void speak()

    }   


    //抽象類不一定有抽象方法
    abstract class Demo2{

        //普通方法
        public void speak()

    }  

3.代碼演示

//定義形狀
public abstract class Shape {

    //抽象類中的普通成員變量
    private double chang;
    private double kuan;

    //抽象類有可以有構造方法
    public Shape() {}

    public Shape(double chang, double kuan) {
        this.chang = chang;
        this.kuan = kuan;
    }

    //抽象類中可以有普通方法
    public void method1(){
        System.out.println("1");
    }

    //抽象方法 有抽象方法的類一定是抽象類
    public abstract void method2();
}

//繼承抽象類一定要實現抽象方法,如果不實現,這個類還是抽象類, 編譯的時候會有提示的
abstract class Test2 extends Shape{
}


//繼承
class Test extends Shape{

    //繼承抽象類一定要實現抽象方法
    @Override
    public void method2() {

    }

    public static void main(String[] args) {
        // 抽象類不能實例化
        // Shape b = new Shape();

        Test test = new Test();
    }
}

3.抽象類的作用

用來描述一種數據類型應該具備的基本特徵(成員變量)和行爲(方法),如何實現這些方法由子類通過方法重寫完成。

4.抽象類的特點

  • 1.抽象類和抽象方法都需要用關鍵字:abstract修飾
  • 2.抽象類不能直接創建對象,因爲調用抽象方法毫無意義,爲什麼沒有意義呢,因爲抽象方法 沒有代碼塊,它只是定義了方法
  • 3.子類繼承抽象類之後,要實現抽象類中的所有抽象方法,否則要將子類也定義爲抽象類

5.抽象類常見的幾個問題描述

  • 5.1抽象類不能創建對象,抽象類中是有構造方法,子類可以通過super調用父類的構造方法,給父類的成員變量賦值,賦值完之後子類就可以使用父類繼承的成員變量。
  • 5.2抽象類一定是個父類,因爲抽象類不能創建對象。
  • 5.3抽象類中可以不定義抽象方法
  • 5.4抽象類中可以定義普通方法(有方法體的方法)
  • 5.5抽象關鍵字不能和private關鍵字共存。因爲private修飾的方法不能被子類重寫,而抽象方法又要求子類要重寫。

第二小節 接口

1.接口的概念

  • 1.1接口也是一種數據類型。它是比抽象類更加抽象的’類’
  • 1.2接口是功能(方法)的集合,如何實現這些功能由實現類(子類)通過方法重寫實現。
  • 1.3接口中的方法都是抽象方法。

2.接口的定義和使用格式

    //定義格式
    interface 接口名{
        // 抽象方法
    }
    //使用格式
    class 類名 implements 接口名 {
        // 重寫抽象方法
    }

3.示例代碼

//抽象類(父類)
public abstract class Animal {
    //  動物都會叫 但是每個動物叫聲都不一樣  所有定義一個抽象方法
    public abstract void jiao();
}
//定義個子類dog繼承動物類
 public class Dog  extends Animal{
    @Override
    public void jiao() {
        System.out.println("汪汪汪");
    }
}
//定義格式
interface 接口名{
    // 抽象方法
}

//寫一個接口給actdog  因爲不是每個狗都會表演
public interface jiekou {
    // 抽象方法
    public abstract void actDog();

}
//寫一個會表演的狗繼承狗類 並且使用接口
public class ActDog extends Dog implements jiekou {
    @Override
    public void actDog() {
        System.out.println("會胸口碎大石");
    }
}
//寫一個測試類進行測試
public class Demo2 {
    public static void main(String[] args) {
        ActDog  dog = new ActDog();
        dog.jiao();
        dog.actDog();

        Dog dog1 = new Dog();
        dog1.jiao();
        //  因爲不是每一個狗都會表演  所以dog1不能調用act方法
        //  dog1.actDog();
    }
}

4. 接口的特點和注意事項

4.1 接口特點

在JDK1.8之前,接口中所有的方法都是抽象方法,在JDK1.8後,接口中的方法可以有默認實現(有方法體)

public interface jiekou {

    // 抽象方法
    public abstract void actDog();

    //默認方法
    public  static void eat() {
        System.out.println("會吃東西");
    };
}
  • 接口沒有構造方法

  • 接口中定義成員變量是常量。

  • 接口不能創建對象,原理跟抽象方法一樣,因爲沒有代碼塊(也是沒有具體的實現方法)

  • 接口可以繼承接口,而且可以多繼承。

  • 接口中的抽象方法有默認的修飾符:public abstract

  • 接口中的常量有默認的修飾符:public static final

4.2 注意事項

Java支持類在繼承一個類的同時實現1個或多個接口。
接口與父類的功能可以重複,均代表要具備某種功能,並不衝突。

當一個類實現了接口時,必須實現其所有的方法,否則這個類必須定義爲一個抽象類。

4.3 接口和抽象類的應用

/**
 * 適配器模式
 */
interface MyInterface{

    //比如定義了n多個方法
    void method();
    void method2();
    void method3();
    void method4();
    void method5();
    void method6();
}

//class Demo implements MyInterface {

    //這樣我就要實現很多個方法了,但是我就只是實現第一個方法
//} 

abstract class  Adapter implements MyInterface{
    @Override
    public void method() {

    }

    @Override
    public void method2() {

    }

    @Override
    public void method3() {

    }

    @Override
    public void method4() {

    }

    @Override
    public void method5() {

    }

    @Override
    public void method6() {

    }
}

class Demo extends Adapter{

    @Override
    public void method() {
        //現在就只需要實現一個方法了
    }
} 

5. 接口和抽象類的區別

5.1.相同點

  • 都不能創建對象
  • 子類或實現類都必須重寫抽象方法

5.2.不同點

  • 接口可以接口且可以多繼承, 類只能單繼承,不能多繼承。
  • 接口中的成員變量是常量了,抽象類可以有普通成員變量,也可以有常量。
  • 抽象類中可以有構造方法(因爲抽象類不能new 出來,所以抽象類的構造方法,只有在子類繼承的時候纔可以調用抽象類的構造方法),接口中沒有構造方法
  • 接口中的抽象方法有默認的修飾符:public abstract,抽象類的抽象方法沒有默認的修飾符。
  • 接口中的常量有默認的修飾符:public static final,抽象類的成員變量沒有默認修飾符。
  • 抽象類中可以有非抽象方法,接口在JDK.18(包括1.8)之後纔可以有非抽象方法。

第三小節 多態

1.多態的概述

多態是java面向對象的第三大特徵,同一種事物表現出來的多種形態則稱爲多態。
比如:張三 ==> 學生 張三 ==> 路人甲 張三 ==> 兒子
比如:狗 ==> 動物 狗 ==> 寵物

2.多態的注意細節,例子,和分析,重點

class Animal{
    int num = 10;
    static int age = 20;

    public void  eat(){
        System.out.println("動物吃飯");
    }

    public static void sleep(){
        System.out.println("動物睡覺");
    }

    public void run(){
        System.out.println("動物跑步");
    }
}

//多態三要素之一:Cat類繼承了Animal類
class Cat extends Animal{
    int num = 80;
    static int age =90;

    String name = "tomcat";

    //多態三要素之二:子類要重寫父類的方法,非靜態方法
    public void  eat(){
        System.out.println("貓吃飯");
    }

    //多態三要素之二:子類要重寫父類的方法,靜態方法
    public static void sleep(){
        System.out.println("貓睡覺");
    }

    public void catchMouse(){
        System.out.println("貓在抓老鼠");
    }
}

class Demo{
    public static void main(String[] args) {

        //多態三要素之三:父類數據類型的引用指向子類對象
        Animal am = new Cat();  //多態的格式,也可以只想接口
        am.eat();   //貓吃飯
        am.sleep();  //動物在睡覺
        am.run();  //動物在奔跑
        System.out.println(am.num);  //10
        System.out.println(am.age);  //20

        //總結:
        //成員變量:編譯看左邊(父類),運行看左邊(父類) --->am.num 和 am.age
        //靜態方法:編譯看左邊(父類),運行看左邊(父類) --->sleep() 靜態和類相關,算不上重寫
        //成員方法:編譯看左邊(父類),運行看右邊(子類) --->eat()

        //多態的好處缺點,不能訪問子類特有的成員:成員變量和成員方法。
        //am.catchMouse();  //編譯報錯
        //System.out.println(am.name);  //編譯報錯

        //如果一定要執行am.name
        Cat cat = (Cat)am;
        System.out.println(cat.name);  //tomcat
    }
}
大家都知道花木蘭替父從軍的例子,花木蘭替父親花弧從軍。那麼這時候花木蘭是子類,花弧是父類。花弧有自己的成員屬性年齡,姓名,性別。花木蘭也有這些屬性,但是很明顯二者的屬性完全不一樣。花弧有自己的非靜態成員方法‘騎馬殺敵’,同樣花木蘭也遺傳了父親一樣的方法‘騎馬殺敵’。花弧還有一個靜態方法‘自我介紹’,每個人都可以問花弧姓甚名誰。同時花木蘭還有一個自己特有的非靜態成員方法‘塗脂抹粉’。但是,現在花木蘭替父從軍,女扮男裝。這時候相當於父類的引用(花弧這個名字)指向了子類對象(花木蘭這個人),那麼在其他類(其他的人)中訪問子類對象(花木蘭這個人)的成員屬性(姓名,年齡,性別)時,其實看到的都是花木蘭她父親的名字(花弧)、年齡(60歲)、性別(男)。當訪問子類對象(花木蘭這個人)的非靜態成員方法(騎馬打仗)時,其實都是看到花木蘭自己運用十八般武藝在騎馬打仗。當訪問花木蘭的靜態方法時(自我介紹),花木蘭自己都是用她父親的名字信息在向別人作自我介紹。並且這時候花木蘭不能使用自己特有的成員方法‘塗脂抹粉’。

-----多態中的向上轉型


那麼終於一將功成萬骨枯,打仗旗開得勝了,花木蘭告別了戰爭生活。有一天,遇到了自己心愛的男人,這時候愛情的力量將父類對象的引用(花弧這個名字)強制轉換爲子類對象本來的引用(花木蘭這個名字),那麼花木蘭又從新成爲了她自己,這時候她完全是她自己了。名字是花木蘭,年齡是28,性別是女,打仗依然那樣生猛女漢子,自我介紹則堂堂正正地告訴別人我叫花木蘭。OMG!終於,終於可以使用自己特有的成員方法‘塗脂抹粉’了。從此,花木蘭完全回到了替父從軍前的那個花木蘭了。並且和自己心愛的男人幸福的過完了一生。

-----多態中的向下轉型

3.多態的使用場景

//作爲形式參數,多態用於形式參數類型的時候可以接收更多類型的對象
public class Demo2 {

    public static void main(String[] args) {

        Animal dog = new Dog();
        feedAnimal(dog);


        Animal p = new pig();
        feedAnimal(p);


        Animal cat = new cat();
        feedAnimal(cat);
    }

    public static void feedAnimal(Animal a) { //Animal a = new Dog();
        a.eat();
    }
}


//作爲返回值類型,多態用於返回值類型的時候可以返回更多類型的對象。
public static void main(String[] args) {
    Animal a = productAnimal(1);
    a.eat();

    Animal d4 = productAnimal(2);
    d4.eat();
    d4.jiao();

    Animal d41 = productAnimal(55);
    d41.eat();
    d41.jiao();
}

//生成動物 type = 1 表示生產狗 type = 2 表示生產貓
public static Animal productAnimal(int type) {
    if (type == 1) {
        return new Dog();
    } else if (type == 2) {
        return new cat();
    }
    return new pig();
}

4.多態的轉型

  • 向上轉型
//當把子類對象賦值給一個父類引用時,便是向上轉型,多態本身就是向上轉型的過程。
使用格式 父類類型 變量名 = new 子類類型();
如:Person p = new Student();
  • 向下轉型(參考基本數據類的強制轉換)

    子類類型 變量名 = (子類類型) 父類類型的變量;
    如:Student stu = (Student) p;  //變量p 實際上指向Student對象

5. instanceof關鍵字

5.1.instanceof的作用

用來判斷某個對象是否屬於某種數據類型。如學生的對象屬於學生類,學生的對象也屬於人類。

5.2.使用格式

boolean b = 對象名 instanceof 類名或接口名;

5.3. 注意事項

如果instanceof右邊是類名,則要求左邊的對象名和類名必須存在子父類關係。

參考:https://www.zhihu.com/question/30082151

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