詳解 繼承(上)—— 工具的抽象與分層

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

本篇博文講解的知識點比較實用,但是,相關知識點太多,所以本人將內容分為上下兩冊, 那麼,本人就不多廢話,直接進入主題進行講解了! 說到“繼承”,大家可能都會想到我們日常中對於這個詞的定義:將先人的 物品 或 意志 傳承給後人,而後人也可以“擇優繼承”,併在先人的基礎上產生 新的物品 或 新的意志。 ...


本篇博文講解的知識點比較實用,但是,相關知識點太多,所以本人將內容分為上下兩冊,
那麼,本人就不多廢話,直接進入主題進行講解了!

說到“繼承”,大家可能都會想到我們日常中對於這個詞的定義:將先人的 物品 或 意志 傳承給後人,而後人也可以“擇優繼承”,併在先人的基礎上產生 新的物品 或 新的意志。

上面這一段話,並不是為了瞎扯才寫出來的,上述的思想就是本人對於JAVA中的“繼承”的一種通俗的理解:
將父類的 成員 或 方法 傳承給 子類 , 而子類也可以選擇自己聲明一個同名的成員,或者 一個同名、同返回值、同參數的方法,併在父類的基礎上 定義 新的成員 或 新的方法 。

通過這樣描述,可能大家會對於繼承的優點就有了基本的認識。
那麼,現在,本人來總結一下 繼承的優點

繼承的優點

  • 提高了代碼的復用性
  • 提高了代碼的維護性
  • 讓類與類之間產生了關係,是多態的前提

在這裡,本人還要提出的一點是:

Object類 是 所有類的基類(即 父類)

這樣一來,想必同學們對於這個知識點就有了大致的認識了,那麼,現在本人來編寫一段代碼來實現一下上述的思想:
首先,先在com.mec.about_inheritance.classes包下,來編寫一個 Parent.java 文件:

package com.mec.about_inheritance.classes;

public class Parent {
    public int parentPublicMember;
    private int parentPrivateMember;
    protected int parentProtectedMember;
    int parentNoneMember;
    
    public Parent() {
        parentPublicMember = 1;
        parentPrivateMember = 2;
        parentProtectedMember = 3;
        System.out.println("Parent 無參構造方法");
    }
    
    public int parentPublicMethod() {
        parentPrivateMethod();
        System.out.println("執行Parent 類的 public 構造方法!");
        return parentPrivateMember;
    }
    
    private void parentPrivateMethod() {
        System.out.println("執行Parent 類的 private 構造方法!");        
    }
    
    protected void parentProtectedMethod() {
        System.out.println("執行Parent 類的 protected 構造方法!");      
    }
    
    void parentNoneMethod() {
        System.out.println("執行Parent 類的 無修飾 構造方法!");                
    }
}

現在,我們在本包(com.mec.about_inheritance.classes)下,來編寫它的子類——Child.java :

package com.mec.about_inheritance.classes;

public class Child extends Parent {
    public Child() {
        this.   //這裡的代碼我們還沒敲完就能看到下圖現象:
    }
}

在這裡插入圖片描述我們能夠觀察到:它的父類的所有 無修飾 和 用protected、public修飾詞修飾的成員 和 方法,在本類中可以調用!

那麼,現在我們創建一個新的包com.mec.about_inheritance.test,在這個包下建立 Parent類 的 包外子類 Son類:

package com.mec.about_inheritance.test;

import com.mec.about_inheritance.classes.Parent;

public class Son extends Parent {
    public Son() {
        this.   //這裡的代碼我們還沒敲完就能看到下圖現象:
    }
}

在這裡插入圖片描述我們能夠觀察到:它的父類的所有 用protected、public修飾詞修飾的成員 和 方法,在本類中可以調用!

那麼,現在我們創建一個新的包com.mec.about_inheritance.test,在這個包下建立 Parent類 的 包外非子類 Demo類:

package com.mec.about_inheritance.demo;

import com.mec.about_inheritance.classes.Child;
import com.mec.about_inheritance.classes.Parent;
import com.mec.about_inheritance.test.Son;

public class Demo {

    public static void main(String[] args) {
        Parent parent = new Parent();
        Child child = new Child();
        Son son = new Son();
        
        parent.     //這裡的代碼我們還沒敲完就能看到下圖現象:
    }

}

在這裡插入圖片描述我們能夠觀察到:它調用的類的所有 用public修飾詞修飾的成員 和 方法,在本類中可以調用!

講到這裡,相信好多同學都已經懵了,畢竟本人也是從學習這個知識點的時期過來的,為了方便同學們對比這幾種的區別,本人現在將其總結羅列到一張表中:
許可權修飾符 總結

修飾符 繼承關係 繼承關係 非派生類引用關係 非派生類引用關係
適用範圍 包內子類 包外子類 包內其他類 包外其他類
public
private
protected
default (或 無修飾)

那麼,本人現在來介紹下,這些 許可權修飾符 的一般使用標準吧:
1.凡是打算為子類繼承的成員和方法,用 protected 修飾;
2.不打算被 包外的類 引用的 成員 和 方法 ,不用寫任何 許可權修飾符 。

我們之前說過,在我們構建一個比較大的JAVA工程時,一般都會用到 “構造方法”。
那麼,現在,本人來講解一下 繼承關係 中的 構造方法
我們還是通過代碼的運行結果來總結結論:
首先,在 com.mec.about_inheritance.constructor 包下建立 Grandfather 類:

package com.mec.about_inheritance.constructor;

public class Grandfather {
    public Grandfather() {
        System.out.println("執行爺爺構造方法!");
    }
}

其次,我們在本包( com.mec.about_inheritance.constructor )下建立Parent 類:

package com.mec.about_inheritance.constructor;

public class Parent extends Grandfather {
    public Parent() {
        System.out.println("執行爸爸構造方法!");
    }
}

然後,我們在本包( com.mec.about_inheritance.constructor )下建立Child 類:

package com.mec.about_inheritance.constructor;

public class Child extends Parent{
    public Child() {
        System.out.println("執行孩子構造方法!");
    }
}

最後,我們建立一個新的包 com.mec.about_inheritance.constructor.test ,併在這個包下建立 Test類:

package com.mec.about_inheritance.constructor.test;

import com.mec.about_inheritance.constructor.Child;

public class Test {

    public static void main(String[] args) {
        new Child();
    }
}

然後,我們來觀察下運行結果:
在這裡插入圖片描述由此,我們可以看出,構造方法 的執行順序
有當前類開始,根據繼承關係,追溯到祖先類,再從上往下執行構造方法

但是,本人在之前的博文中說過,若一個類沒有定義無參構造方法,則JVM會預設執行一個無參構造方法。但是,在繼承這裡,正是由於這個原因,會出現一些錯誤,如下:
我們現在對 Grandfather類 進行如下改變:

package com.mec.about_inheritance.constructor;

public class Grandfather {
    private int one;
    private int two;
    
    public Grandfather(int one, int two) {
        this.one = one;
        this.two = two;
        System.out.println("執行爺爺構造方法!");
    }

    public int getOne() {
        return one;
    }

    public void setOne(int one) {
        this.one = one;
    }

    public int getTwo() {
        return two;
    }

    public void setTwo(int two) {
        this.two = two;
    }
    
}

但是,就在這時,我們能夠發現,Parent類那裡竟然出現了錯誤:
在這裡插入圖片描述錯誤提示說:父類Parent 的無參構造方法未定義,Parent類 無參構造方法必須執行另一種 父類 的構造方法。
簡單來講,就是說:因為Grandfather 類沒有無參構造方法。要 Parent 執行 另一種 父類構造方法。
其實,Grandfather 類並不是沒有構造方法,只是沒有無參構造方法!
所以,這裡執行 Grandfather 類的雙參構造方法!

現在,本人對 Parent類 做如下改變:

package com.mec.about_inheritance.constructor;

public class Parent extends Grandfather {
    public Parent() {
        super(0, 0);
        System.out.println("執行爸爸構造方法!");
    }
}

在這裡插入圖片描述
可以看到,現在沒有問題了!

由上面的代碼展示,我們可以看出繼承有如下特點

繼承的特點

  • Java只支持單繼承,不支持多繼承(即 一個類只能擁有一個父類)
  • Java支持 多層繼承(繼承體系)

但是,雖然這樣很方便,繼承也是存在著條件的:

  1. 子類只能繼承父類所有非私有的成員(成員方法和成員變數)
  2. 子類不能繼承父類的構造方法,但是可以通過super(待會兒講)關鍵字去訪問父類構造方法
  3. 不要為了 部分功能 而去 繼承

那麼,在本篇博文的末尾,本人要提出的一點是:我們雖然可以用“繼承”提高代碼的復用性,
但是,“繼承”同樣存在很大的弊端

繼承的弊端: 使得 類的耦合性增強

這違背了我們的開發原則之一的 —— 高內聚,低耦合
(所謂“耦合”—— 類與類的關係
所謂 “內聚”—— 自己完成某件事情的能力)

相信看到這的同學們,一定對於super(0, 0) 這一行代碼十分好奇吧,那麼,請觀看本人的下半篇博文——《詳解 繼承(下)—— super關鍵字 與 多態》


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

-Advertisement-
Play Games
更多相關文章
  • 線程的五種狀態 線程從創建到銷毀一般分為五種狀態,如下圖: 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 ...
  • 接上篇博文—— "《詳解 繼承(上)—— 工具的抽象與分層》" 廢話不多說,進入正題: 本人在上篇“故弄玄虛”,用super();解決了問題,這是為什麼呢? 答曰:子類中所有的構造方法 預設 都會訪問父類中 空參數的構造方法 (拓展:由於這個原理,我們今後所做的“ 工具類 ”都必須要帶上無參構造) ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...