Java開發筆記(四十九)關鍵字super的用法

来源:https://www.cnblogs.com/pinlantu/archive/2019/01/16/10279686.html
-Advertisement-
Play Games

前面介紹瞭如何從Bird類繼承而來Swallow類,按道理子類應當繼承父類的所有要素,但是對於構造方法來說,Swallow類僅僅繼承了Bird類的預設構造方法,並未自動繼承帶參數的構造方法。如果子類想繼續使用父類的其它構造方法,就得自己重寫心儀的構造方法。例如老鷹屬於鳥類,那麼可以編寫繼承自Bird ...


前面介紹瞭如何從Bird類繼承而來Swallow類,按道理子類應當繼承父類的所有要素,但是對於構造方法來說,Swallow類僅僅繼承了Bird類的預設構造方法,並未自動繼承帶參數的構造方法。如果子類想繼續使用父類的其它構造方法,就得自己重寫心儀的構造方法。例如老鷹屬於鳥類,那麼可以編寫繼承自Bird類的Eagle類,同時要在Eagle類內部重新定義擁有多個輸入參數的構造方法,由此得到如下所示的Eagle類代碼:

//定義了一個繼承自鳥類的老鷹類
public class Eagle extends Bird {

	// 老鷹類重寫了帶三個參數的構造方法,則不使用沒有輸入參數的構造方法
	public Eagle(String name, int sexType, String voice) {
		// 利用super指代父類的構造方法名稱
		super(name, sexType, voice);
	}
}

註意到如上代碼用到了關鍵字super,它的字面意思是“超級的”,但並非說它是超人,而是用super指代父類的名稱,所以這裡“super(name, sexType, voice)”實際表達的是“Bird(name, sexType, voice)”,也就是依然利用了Bird類的同名且同參數的構造方法。外部若想創建Eagle類的實例,就要調用新定義的帶三個參數的構造方法,此時創建實例的代碼如下所示:

	// 通過構造方法設置屬性值
	private static void setConstruct() {
		// 調用Bird類帶三個參數的構造方法
		Bird cuckoo = new Bird("杜鵑", 1, "布穀");
		System.out.println(cuckoo.toString());
		// Eagle類重寫了帶三個參數的構造方法
		Eagle eagle = new Eagle("鷹" , 0, "啁啁");
		System.out.println(eagle.toString());
	}

 

在類繼承的場合,關鍵字super表示父類,對應的this表示本類。如同this的用法一般,super不但可用於構造方法,還可作為成員屬性和成員方法的首碼,例如“super.屬性名稱”代表父類的屬性,“super.方法名稱”代表父類的方法。
在中文世界里,性別名稱的“雄”和“雌”專用於野生動物,而家畜、家禽的性別應當採用“公”和“母”,比如公雞、公牛、母鴨、母豬等等。前述的Bird類,預設的性別名稱為“雄”和“雌”,顯然並不適用於家禽。為此幾種家禽從Bird類派生而來時,需要重新定義它們的性別名稱屬性,也就是重寫setSexType方法,在該方法內部另行對sexName欄位賦值。以鴨子類為例,重寫方法後的類定義代碼如下:

//定義了一個繼承自鳥類的鴨子類
public class Duck extends Bird {
	
	// 定義一個家禽類的性別名稱
	private String sexName;

	public Duck(String name, int sex) {
		// 利用super指代父類的構造方法名稱
		super(name, sex, "嘎嘎");
	}

	public void setSexType(int sexType) {
		// 方法內部再調用自身方法,會變成遞歸調用,如果沒有退出機制就變成死迴圈了
		//setSexType(sexType);
		// 在方法前面添加首碼“super.”,表示這裡調用的是父類的方法
		super.setSexType(sexType);
		// 修改家禽類的性別名稱,此時父類和子類都有同名屬性sexName,不加首碼的話預設為子類的屬性
		sexName = (sexType==0) ? "公" : "母";
		//this.sexName = (sexType==0) ? "公" : "母";
	}

	// 父類的getSexName方法需要重寫,否則父類的方法會使用父類的屬性
	public String getSexName() {
		return this.sexName;
	}

	// 父類的toString方法需要重寫,否則父類的方法會使用父類的屬性
	public String toString() {
		String desc = String.format("這是一隻%s%s,它會%3$s、%3$s地叫。", 
				this.sexName, getName(), getVoice());
		return desc;
	}
}

以上的Duck類代碼,看起來頗有些奇特之處,且待下麵細細道來:

1、由於Bird類的sexName屬性為private類型,表示其為私有屬性,不可被子類訪問,因此Duck類另外定義自己的sexName屬性,好讓狸貓換太子。
2、重寫後的setSexType方法,只有sexName屬性才需額外設置,而sexType屬性仍遵循父類的處理方式,故此時要調用父類的setSexType方法,即給該方法添加首碼“super.”。
3、因為Duck類重新定義了sexName屬性,所以與sexName有關的方法都要重寫,改為讀寫當前類的屬性,否則父類的方法依舊操作父類的屬性。
再來看一個以super修飾成員屬性的例子,倘若Bird類的sexName屬性為public類型,就意味著子類也可訪問它,那麼Duck類便能通過“super.sexName”操作該屬性了。此時新定義的DuckPublic類代碼就變成下麵這樣:

//演示同名的父類屬性、子類屬性、輸入參數三者的優先順序順序
public class DuckPublic extends Bird {

	public DuckPublic(String name, int sex) {
		super(name, sex, "嘎嘎");
	}

	public void setSexType(int sexType) {
		super.setSexType(sexType);
		// 若想對父類的屬性直接賦值,則考慮把父類的屬性從private改為public
		super.sexName = (sexType==0) ? "公" : "母";
		// 父類和子類擁有同名屬性,則不帶首碼的屬性欄位預設為子類屬性
		//sexName = (sexType==0) ? "公" : "母";
		//this.sexName = (sexType==0) ? "公" : "母";
	}

	private String sexName;

	public void setSexName(String sexName) {
		// 輸入參數與類的屬性同名,則不帶首碼的參數欄位預設為輸入參數
		this.sexName = sexName;
	}
}

假設DuckPublic類也定義了同名屬性,並且另外實現了setSexName方法,於是該類裡面將會出現三個sexName,分別是:super.sexName表示父類的屬性,this.sexName表示本類的屬性,而setSexName內部的sexName表示輸入參數。要是三者同時出現兩個,必定有一個需要添加“super”或者“this”的首碼,不然編譯器哪知同名欄位是啥含義?或者說,假如有一個sexName未加任何首碼,那麼編譯器應該優先認定它是父類屬性,還是優先認定它是本類屬性,還是優先認定它是輸入參數?對於這些可能產生欄位名稱混淆的場合,Java制定了下列的優先順序判斷規則:

1、方法內部存在同名的輸入參數,則該欄位名稱預設代表輸入參數;
2、方法內部不存在同名的輸入參數,則該欄位名稱預設代表本類的成員屬性;
3、方法內部不存在同名的輸入參數,且本類也未重新定義同名的成員屬性,則該欄位名稱只能代表父類的成員屬性;
概括地說,對於同名的欄位名稱而言,其所表達含義的優先順序順序為:輸入參數>本類屬性>父類屬性。



更多Java技術文章參見《Java開發筆記(序)章節目錄


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

-Advertisement-
Play Games
更多相關文章
  • 分散式架構設計:1、橫向分層,將系統在橫向維度上切分成幾個部分,每個部分負責一部分相對比較單一的職責,例如:MVC經典模式。2、縱向分割,將系統功能模塊歸類切分成幾個部分,包裝成高內聚低耦合的模塊單元,不同功能模塊直接通過遠程調用協助工作。3、緩存技術,將是改善系統性能的第一手段,從上到下依次:瀏覽 ...
  • 沒圖,別找了。。。 我在MyEclipse上從SVN中導項目,導下的項目跑不起來,發現tomcat的classes中是空文件夾。 以下是在網上找的其他方法: 1.確保:Project->build automatically 已經被選上。(預設選上) 2.project->clean項目,一般會重新 ...
  • 1. 知乎文章圖片爬取器之二博客背景 昨天寫了知乎文章圖片爬取器的一部分代碼,針對知乎問題的答案json進行了數據抓取,博客中出現了部分寫死的內容,今天把那部分信息調整完畢,並且將圖片下載完善到代碼中去。 首先,需要獲取任意知乎的問題,只需要你輸入問題的ID,就可以獲取相關的頁面信息,比如最重要的合 ...
  • 一、WebSocket與HTTP長輪詢 WebSocket 屬於HTML5 規範的一部分,提供的一種在單個 TCP 連接上進行全雙工通訊的協議。允許服務端主動向客戶端推送數據。在 WebSocket API 中,瀏覽器和伺服器只需要完成一次握手,兩者之間就直接可以創建持久性的連接,併進行雙向數據傳輸 ...
  • 在前面幾篇討論里我們介紹了在集群環境里的一些編程模式、分散式數據結構及具體實現方式。到目前為止,我們已經實現了把程式任務分配給處於很多伺服器上的actor,能夠最大程度的利用整體系統的硬體資源。這是因為通過akka-cluster能夠把很多伺服器組合成一個虛擬的整體系統,編程人員不需要知道負責運算的 ...
  • 引言 logging 的基本用法網上很多,這裡就不介紹了。在引入正文之前,先來看一個需求: 假設需要將某功能封裝成類庫供他人使用,如何處理類庫中的日誌? 數年前在一個 C# 開發的項目中,我用了這樣的方法:定義一個 logging 基類,所有需要用到日誌的類都繼承這個基類,這個基類中定義一個 Log ...
  • 背景:聽說ClassLoader類載入機制是進入BAT的必經之路。 ClassLoader總述: 普通的Java開發其實用到ClassLoader的地方並不多,但是理解透徹ClassLoader類的載入機制,無論是對我們編寫更高效的代碼還是進BAT都大有裨益;而從“黃埔軍校”出來的我對ClassLo ...
  • 近日在虛擬機下的QT5.11.2安裝出現了一個bug,折騰好久才搞定。 環境:vmware + debain 9.5 + qt5.11.2 。 QT_DIR = /Qt5.11.2/5.11.2/gcc_64/mkspecs 找了各大網站、博客,基本都是說直接安裝openGL的,然而我的虛擬機安裝o ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...