詳解 繼承(下)—— super關鍵字 與 多態

来源:https://www.cnblogs.com/codderYouzg/archive/2020/02/29/12385960.html
-Advertisement-
Play Games

接上篇博文—— "《詳解 繼承(上)—— 工具的抽象與分層》" 廢話不多說,進入正題: 本人在上篇“故弄玄虛”,用super();解決了問題,這是為什麼呢? 答曰:子類中所有的構造方法 預設 都會訪問父類中 空參數的構造方法 (拓展:由於這個原理,我們今後所做的“ 工具類 ”都必須要帶上無參構造) ...


接上篇博文——《詳解 繼承(上)—— 工具的抽象與分層》
廢話不多說,進入正題:

本人在上篇“故弄玄虛”,用super();解決了問題,這是為什麼呢?
答曰:子類中所有的構造方法預設都會訪問父類中空參數的構造方法
(拓展:由於這個原理,我們今後所做的“工具類”都必須要帶上無參構造)

那麼,父類沒有無參構造方法,子類怎麼辦?

解決父類沒有無參構造的手段

  • 父類中添加一個無參的構造方法
  • 子類通過super去調用父類其他的帶參的構造方法
  • 子類通過this去調用本類的其他構造方法 (本類其他構造也必須首先訪問了父類構造)

那麼,現在,本人來講解一下super吧:

super:

super class 其實就是超類、基類、父類的意思。

在這裡本人來提醒一點:

Object類 是 所有類的基類

super有兩個嚴格要求:

  1. 只能出現在構造方法中;
  2. 如果有super(),則它必須是構造方法的第一條語句
    (所以,super() 和 this() 不能同時出現在同一個構造方法中)

而且,不論我們在 子類 中的構造方法是 無參 還是 帶參,在預設情況下,JVM只調用基類的無參構造方法!

我們在上篇博文開頭就提到過,我們在“繼承”的過程中可以“擇優繼承”,那麼,本人現在就來講解下,如何“擇優繼承”:

我們實現這個結果的方法是:方法的覆蓋
那麼,現在我們對於方法的覆蓋進行以下說明

(1)僅存在於有繼承關係的類之間;
(2)子類的方法名名稱參數個數類型,必須和被覆蓋的父類保持一致;
(3)子類的返回值必須和被覆蓋的父類保持一致;
(4)子類方法的修飾符不能“低於”被覆蓋的分類方法;
(5)若違反了(2),則實質上是方法的重載,並非覆蓋

(本人在這裡只是為了使同學們能瞭解後面的代碼,僅在這裡淺談覆蓋,在本人後續博文中會對於方法的覆蓋進行深度講解)

現在我們來舉一個簡單有趣的例子:
我們先建立一個包 com.mec.about_override.demo,併在包下建立如下類:
Animal.java:

package com.mec.about_override.demo;

public class Animal {
    private String name;
    
    public Animal(String name) {
        this.name = name;
    }
    
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
    
    public void cry() {
        System.out.println("動物的叫聲!");
    }
    
}

Dog.java:

package com.mec.about_override.demo;

public class Dog extends Animal {
    public Dog(String name) {
        super(name);
    }
    
    public void cry() {
        System.out.println("汪汪");
    }
}

Demo.java:

package com.mec.about_override.demo;

public class Demo {

    public static void main(String[] args) {
        Animal animal =new Animal("動物");
        animal.cry();

        Dog dog = new Dog("二愣子");
        dog.cry();
    }
}

我們現在來編譯一下,結果如下:
在這裡插入圖片描述可以看出,我們在 Animal類中所編寫的 cry() 方法被覆蓋了!

多態:

現在,本人來介紹本篇博文的另一個知識點 —— 多態

多態 —— 某一個事物,在不同時刻表現出來的不同狀態

首先,多態是有 條件的:

多態前提

  • 要有繼承關係
  • 要有覆蓋(方法重寫)
    其實沒有也是可以的,但是如果沒有這個就沒有意義
  • 要有父類引用指向子類對象
    形如:
    父 f = new 子();

接下來,本人來講解一個非常有趣的 知識點:
基類 與 派生類 之間的 強制類型轉換:
我們對上面的 Dog類 和 Demo類 做如下修改:
Dog.java:

package com.mec.about_override.demo;

public class Dog extends Animal {
    public Dog(String name) {
        super(name);
    }
    
    public void cry() {
        System.out.println("汪汪");
    }
    
    public void dogAction() {
        System.out.println("狗子快跑!");
    }
}

Demo.java:

package com.mec.about_override.demo;

public class Demo {

    public static void main(String[] args) {
        Animal animal =new Animal("動物");
        animal.cry();
        
        Dog dog = new Dog("二愣子");
        dog.cry();
        
        Animal otherAnimal = (Animal) dog;
        dog.dogAction();
        dog.cry();
    }
    
    
}

運行結果如下:
在這裡插入圖片描述
現在可能就有同學有疑問了這裡的輸出結果竟然是“汪汪”而不是“動物的叫聲”!

這裡對上述問題做出解釋:

基類 與 派生類 之間的 強制類型轉換 遵循如下原則

  1. 對象的類型 約束 對象所能引用成員方法,但是,不能更改 成員 和 方法 的本質內容;
  2. 對於方法,強轉不能改變 其所 實際指向 的 代碼 的首地址; 對象 的類型 決定 對象 所能引用的 對象和方法 的種類(即:Animal類型); 對象 所能調用的 成員 和 方法 取決於所申請空間的 對象和方法(即:Dog類型);
  3. 子類對象 可以被強轉成 父類類型,但父類對象 不能被強轉成 子類類型,因為父類對象中可能不存在子類類型的成員和方法

對於以上的現象,可能同學們在初學時會對子類與基類之間的關係感覺有點頭暈。
別怕,在這裡,本人還要介紹一個知識點,來輔助我們識別它們之間的關係:

多態中的成員訪問特點

  • 成員變數 :
    編譯看左邊,運行看左邊。
  • 構造方法 :
    創建子類對象的時候,會訪問父類的構造方法,對父類的數據進行初始化。
  • 成員方法 :
    編譯看左邊,運行看右邊。
  • 靜態方法 :
    編譯看左邊,運行看左邊。
    (靜態和類相關,算不上重寫,所以,訪問還是左邊的)

那麼,為什麼要存在多態這個機制呢?

多態的好處

  1. 提高了代碼的維護性(繼承保證)
  2. 提高了代碼的擴展性(由多態保證)

那麼,繼承的所有知識點也就講解完成了,這篇博文寫完已經是當天的凌晨3:17了,本人也是實在困得不行了,可見,兢兢業業的良心博主啊(哈哈,這裡小小抱怨一下,勿怪)。
若是對上述知識點或代碼有任何疑惑、意見或者建議,請在下方評論區提出,本人將儘早予以答覆,覺得有所幫助的同學請留下小贊贊,謝謝!!!


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 匿名(lambda)函數: 作用:創始一個匿名函數對象,同 def 類似,但不提供函數名,只是一個表達式,lambda比函數簡單且可以隨時創建和銷毀,有利於減少程式的偶合度。lambda的主體是一個表達式,而不是一個代碼塊。僅僅能在lambda表達式中封裝有限的邏輯進去。lambda 函數擁有自己的 ...
  • 線程的五種狀態 線程從創建到銷毀一般分為五種狀態,如下圖: 1) 新建 當用new關鍵字創建一個線程時,就是新建狀態。 2) 就緒 調用了 start 方法之後,線程就進入了就緒階段。此時,線程不會立即執行run方法,需要等待獲取CPU資源。 3) 運行 當線程獲得CPU時間片後,就會進入運行狀態, ...
  • 題目1 求平均分 輸入:兩行 第一行是分數個數n 第二行是這n個分數,以空格隔開 輸出: 去掉最高分與最低分後的平均成績 #include<stdio.h> float buf[1001]; void fun(int n){ for(int i=0;i<n;i++){ for(int j=0;j<n ...
  • #include <iostream> //#include(預處理指令) iostream(所嵌入的頭文件(cout,<<等操作的有關信息就是在該文件中聲明的)) using namespace std; //針對命名空間的指令 int main(){ //int(返回值類型) main(主函數名 ...
  • 有監督學習 常用分類演算法 KNN:K近鄰分類器。通過計算待分類數據點,與已知數據中所有點的距離,取距離最小的前K個點,根據"少數服從多數"的原則,將這個數據點劃分為出現次數最多的那個類別。 在sklearn中,使用sklearn.neighbors.KNeighborsClassifier創建K鄰近 ...
  • 1、格式 符號為大括弧 集合沒有順序,也不支持下標操作 集合沒有重覆的數據 2、定義的類型 #有數據 s1 = {1, 3, 4} # {1,3,4} s2 = set('asdadsdas') # {'a','s','d'} 集合沒有重覆數據,也沒有順序 # 空集合 s3 = {} # dict ...
  • 1、格式 符號為大括弧 數據為鍵值對形式出現(字典數據與數據順序沒有關係,即字典不支持下標) 各個鍵值對之間逗號隔開 2、定義的類型 # 有數據 dict1 = {'name': '小明', 'sex': '男'} # 空字典 dict2 = {} dict3 =dict() # 函數定義 3、常用 ...
  • Spring Cloud官網: 本篇主要講 "Spring Cloud Config" ,參考內容如下: "Spring Cloud Config 2.2.1.RELEASE參考文檔" "Spring Cloud Config 實現配置中心,看這一篇就夠了" 實現簡單的配置中心 配置文件就在Spri ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...