Java:继承之super关键字,继承之私有权限,继承之方法重写,继承之object类,继承之简单工厂模式
一、繼承的概念及用法
????????繼承背后的思想就是? ? ? ? 基于已存在的類來構建新類
????????當從已存在類繼承時,就重用了它的方法和屬性,還可以添加新的方法和屬性來定制新類以應對需求
? ? ? ? 約定:從其他類導出的類叫做子類
? ? ? ? ? ? ? ? ? ? ? ? 被導出的類叫父類
? ? ? ? 在Java中,除了object類之外,所有類都是子類,都只有唯一的父類
首先先看一段c代碼
這邊兩個結構體,一個Person結構體,一個Student結構體
發現這里面有很多重復的地方,造成了代碼的浪費
?如果你改成這樣,邏輯上有點奇怪
?那么Java就是來解決這個尷尬的問題
生活中,繼承的概念隨處可見
? ? ? ? 繼承需要符合的關系:is-a;父類更通用更抽象、子類更特殊更具體
繼承背后的思想就是? ? ? ? 基于已存在的類來構建新類:
? ? ? ?這是一個已存在的類
struct Person
{
?? ?int name;
?? ?char *address;? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
?? ?void (*pEat)();
?? ?void (*pDrink());
};
?
這是一個新類
struct Student
{
?? ?int name;
?? ?char *address;
?? ?void (*pEat)();
?? ?void (*pDrink());
?? ?
?? ?int score;
?? ?void (*goToSchool)());
};
我們肯定要基于person構建student,因為person和student在代碼上有重復,從我們人為的角度,學生也是一種人,
? ? ? ??
???當從已存在類繼承時,就重用了它的方法和屬性,還可以添加新的方法和屬性來定制新類以應對需求
? ? ? ? 約定:從其他類導出的類叫做子類
? ? ? ? ? ? ? ? ? ? ? ? 被導出的類叫父類
這種情況下student叫做子類,person叫做父類
? ? 在Java中,除了object類之外,所有類都是子類,都只有唯一的父類:
那么這個object是什么呢?
比如我們以前寫過的代碼demo2.java里面有兩個類
一個是demo2,一個是student
我們來看一下student 的父類是什么
選擇student 然后在選擇F4那個
?會看到student的父類是一個object
?然后同樣的方法,我們再來看一下demo2的父類
這些類創建的時候, 沒有顯示繼承于誰,默認都是繼承object
?
繼承在oop中不可缺
創建一個類時,總是在繼承
繼承的意義
????????代碼重用? ? ? ? 體現不同抽象層次
父子類關系
? ? ? ? 父類更抽象,更一般? ? ? ? 子類更具體,更特殊
繼承在oop中不可缺
創建一個類時,總是在繼承
你寫也是在繼承,不寫也是在繼承,你不寫就是繼承object
在java語言中,用extends關鍵字來表示一個類繼承另一個
Public? ?class? ?Teacher? ?extends? ? ?Person{
? ? ? ? //其余代碼省略? ? ? ??
}
我么現在新建一個工程
記得新建類的時候要大寫開頭?
?然后我們把之前的代碼拿過來修改一下
?下面還是沒有繼承的概念,一個person類,一個student 類,只是把c語言的結構體,改成java面向對象
?代碼運行一下
?運行結果
?那我們引入繼承的概念是什么意思呢?
student繼承于person
繼承很重要的一點是代碼的復用
也就是說第17行到24行,可以去掉
但是如果我們直接刪掉的話
錯誤提示name cannot be resolved or is not a field
name不是一個普通的變量
錯誤提示The method eat() is undefined for the type Student
學生這個類沒有eat
?我們加上一個extends Person 錯誤就消失啦
?運行一下
?在修改一下
?運行結果
二、Java繼承之super關鍵字
? ? ? ??super關鍵字的特點
? ? ? ? ? ? ? ?super和this 關鍵字的特點類似:super 代表的是父類對象的引用
? ? ? ? ? ? ? ? 當子父類的成員出現同名時,可以通過super 來區分
? ? ? ? ? ? ? ? 子類的構造方法中,通過super關鍵字調用父類的構造方法?
? ? ? ? public class JavaTeacher extends Teacher{
? ? ? ? ? ? ? ? public JavaTeacher(String name,String school){
? ? ? ? ? ? ? ? ? ? ? ? super(name,school);? ? ?//通過調用父類的構造方法,完成對相關字段值的初始化
????????}
}
強調:當構造一個子類對象的時候一定會先先調用父類的構造方法來構造父類的對象。調用父類構造方法的語句必須是子類構造方法中的第一條指令
?super和this 關鍵字的特點類似:super 代表的是父類對象的引用
this 代表的是該類對象的引用
? 子類的構造方法中,通過super關鍵字調用父類的構造方法?
? ? ? ? ? ? ? ? 比如說我這里面 的JavaTeacher 繼承于Teacher
? ? ? ? ? ? ? ? ? ? ? ? 那么JavaTeacher 的構造方法怎么寫呢?如果有兩個參數,那么父類也存在有兩個參數的構造方法,那么通過super 調用父類的構造方法來實現Java Teacher的初始化
? ? ? ? public class JavaTeacher extends Teacher{
? ? ? ? ? ? ? ? public JavaTeacher(String name,String school){
? ? ? ? ? ? ? ? ? ? ? ? super(name,school);? ? ?//通過調用父類的構造方法,完成對相關字段值的初始化
????????}
}
子類的構造方法中,通過super關鍵字調用父類的構造方法?
我們先新建一個工程(ctrl +c? ? ctrl +v? 復制之前的)
?比如現在我們父類有一個構造方法
構造方法的作用,一般給屬性賦初值
我們這樣一寫出問題了
Implicit super constructor Person() is undefined for default constructor. Must define an explicit constructor
也就是說構造方法,不寫的話,會默認一種無參的構造方法
當你在父類寫構造方法的時候(第8到11行),父類就不存在無參的
?無參的構造方法什么時候才有呢?
你沒有自己寫構造方法,系統會自動給你做一個
?解決方式有兩種
子類默認沒有構造方法,沒寫的話就會調用無參構造方法
1、public 給他提供一個無參的構造方法(第8行)
?2、去調用父類的構造方法,參數是肯定需要的
錯誤提示第30行
Implicit super constructor Person() is undefined. Must explicitly invoke another constructor
他不認定我是個構造方法
?
?那么如何才能正確呢?調用父類的初始化
?
?那么如果我們this.name =name;
?? ??????????????????? ?this.address =address;
可以嗎?
不可以,這是他設置的一種機制
如果你父類里面存在兩個有參的構造方法,你的子類的構造方法,需要去調用父類的構造方法,來初始化里面的參數
?
子類的構造方法中,通過super關鍵字調用父類的構造方法?:
比如說父類的構造方法有多種
子類繼承的時候,繼承一種構造方法,跟父類多少種沒有關系
但是可以認定的話,子類必須調用父類的構造化方法來初始化自己
你不調用父類的話,單獨寫39行到41行
會產生錯誤
Implicit super constructor Person() is undefined. Must explicitly invoke another constructor
不認定你的構造方法是存在的
所以子類只能調用父類的構造方法
?
?當然你可以在自己的構造方法中添加一些語句,這是允許的
你去調用super 的時候,父類的構造方法也會被調用
現在person里面我們做了address 和name ,所以要傳參
我們把多余 都去掉只看關于構造方法的代碼
?
?運行結果
new一個構造方法的時候,36行會被調用,學生被調用的時候,他會調用父類的,所以父類的構造方法會被打印出來,當然之前會把11行,和12行給初始化掉,緊接著打印自己的子類構造方法
?我們添加點代碼看看,第57行
?運行結果
當子父類的成員出現同名時,可以通過super 來區分
我想加個eat,在子類這面????????47,49行
然后可以調用父親的eat????????48行
子類有eat,父類有eat ,你可以調用super ,來調用父類的
?函數可以這樣做,基本變量也可以這樣做
?運行結果
三、Java繼承之私有權限
對繼承過來的方法和權限做一些研究
對于public 沒什么好研究的,不論是子類對他的繼承還是其他包里面對他的調用都是沒有什么問題的
關鍵是私有的,假如我把address改成私有的變量????????第6行private
?
?
?目前還沒有錯,
我們在new 一個student的時候,傳遞的是"哪",
"哪"student? ?????????他會調用父類的student讓這個地址初始化? ? ?第40行
我們再寫一個函數吧? ? ? ? ?第32行? 33行
通過函數的默認屬性,或者公開的屬性printAddr,第32行
????????????????????????來訪問父類里面的private 這個屬性? ?第6行
我們要研究這個private修飾的這個屬性? ? ? 第6行 ??是否會被student繼承過來? ? ??
如果你看到是“哪”,說明私有屬性也是可以繼承的
第32行到34行,第66行
?
?運行一下
我們看到address是可以被繼承過來的
那么如果把方法的權限給他改成private 呢?
馬上就出現問題了
The method printAddr() from the type Person is not visible
雖然你的63行 student是繼承于父類,但是對父類里面的方法是不繼承的
?
?之前我們講封裝的時候,private是只供給同一個類,作為一個屬性的話,是可以訪問 的到
但是作為一個方法的話,是沒辦法訪問的
????????????????????????public ? ? ? ? 該類或非該類均可訪問
? ? ? ? ? ? ? ? ? ? ? ? private ? ? ? ?只有該類可以訪問
? ? ? ? ? ? ? ? ? ? ? ? protected ? ? ? ?該類及其子類的成員可以訪問,同一個包中的類也可訪問
? ? ? ? ? ? ? ? ? ? ? ? 默認 ? ? ? ? ? ? ? ?同一個包中的類可以訪問
? ? ? ? 位置 ? ? ? ? ? ? ? ? ? ? ? ?private ? ? ? ? ? ? ? ?默認 ? ? ? ? ? ? ? ?protected ? ? ? ? ? ? ? ?public
?同一個類 ? ? ? ? ? ? ? ? ? ? ? ? ? ? 是 ? ? ? ? ? ? ? ? ? ? ?是 ? ? ? ? ? ? ? ? ? ? ? 是 ? ? ? ? ? ? ? ? ? ? ? ?是?
?同一個包內的類 ? ? ? ? ? ? ? ? ? 否 ? ? ? ? ? ? ? ? ? ? ?是 ? ? ? ? ? ? ? ? ? ? ?是 ? ? ? ? ? ? ? ? ? ? ? ?是
? 不同包內的子類 ? ? ? ? ? ? ? ?否 ? ? ? ? ? ? ? ? ? ? ? ?否 ? ? ? ? ? ? ? ? ? ? ? ?是 ? ? ? ? ? ? ? ? ? ? ? ?是
不同包并且不是子類 ? ? ? ? ? ?否 ? ? ? ? ? ? ? ? ? ? ? 否 ? ? ? ? ? ? ? ? ? ? ? ?否 ? ? ? ? ? ? ? ? ? ? ? ? ?否
屬性的話,比如這面的學生,我封裝了一個屬性
我們在student這面做一個函數,用this 的方式訪問address是訪問不到的? ? ? ? ?第55行? 56行
The field Person.address is not visible
雖然剛才我們的第67行的“哪”? 被設置進去了,但是是通過父類的構造方式設置的
我們調用的是super 的構造方法,來對他設置的?
繼承的時候,你會發現私有的成員也沒被student 繼承過來,但為什么student 剛才既能被設置也能打印呢?因為我們構造student 是通過父類的構造方法來設置的,打印也是父類這面的printInfo設置的
相當于以前的類似的get 和set 函數的作用通過共有的函數,訪問私有的屬性
私有的方法還好,就是私有的屬性,會造成一個錯覺,我們的私有的屬性也被繼承過來一樣
實際上父類所有私藏的東西,子類都是不知道的
私有的為什么可以這樣用呢?Student s = new Student("ta","哪");
因為我們在new 的時候間接調用了構造方法,調的是父親的構造方法,實例化的是父親的一個對象,所以我們調用父親的構造方法,會間接的訪問到address
我們在打印的時候也是一樣的,會間接訪問到父親的printInfo,會間接的打印address
?
?
如果我們改一下呢?第32行
?
?運行結果
四、Java繼承之方法重寫
什么是方法重寫
? ? ? ? ? ? ? ? 方法重寫是指子類可以根據需要對從父類繼承來的方法進行改寫,
? ? ? ? ? ? ? ? 是多態機制的前奏
方法重寫注意點
? ? ? ? ? ? ? ? 重寫方法必須和被重寫方法具有相同的方法名稱、參數列表和返回值
? ? ? ? ? ? ? ? 重寫方法不能比被重寫方法有更嚴格的訪問權限
? ? ? ? ? ? ? ? 父類中的私有方法,不能被重寫
? ? ? ? ? ? ? ? 在子類重寫的方法中繼續調用父類被重寫的方法可以通過super.函數名獲取
.
.
重寫方法必須和被重寫方法具有相同的方法名稱、參數列表和返回值:
也就是說函數的原型長得一摸一樣
? 重寫方法不能比被重寫方法有更嚴格的訪問權限:
如果父類是一個public的方法,你去重寫的public方法的時候,不能把他的權限改為私有方法,或者默認方法
父類中的私有方法,不能被重寫
連我們的繼承都是沒有繼承過來的,更別說重寫了
假設你父類有一個私有方法,你寫了一個方法,只有權限不一樣,其他的都一樣,會發生什么情況
?
新建一個工程
方法重寫和方法重載是不一樣的
方法重載:構造函數就是一種重載的方式,方法名字一樣,參數列表不一樣
方法重寫:名字,參數列表,返回值,權限都是一樣的
一個類person類,有name,有address?
一個類是student類繼承了person類,添加了一個屬性叫score
重寫方法必須和被重寫方法具有相同的方法名稱、參數列表和返回值
比如說我們現在把????????public void printInfo(){
?? ??????????????????????????????????? ?System.out.println("name="+name);
?????????????????????????????????????????? ?}
????????????????????????????????????????拿來重寫
?然后我們實例化一個student,無參的構造方法
運行結果
第21行? 你這個參數列表屬性都和? 第8行? ?一摸一樣,但是呢,他優先的調用的是子類的
?能不能調用父類的呀
在子類重寫的方法中繼續調用父類被重寫的方法可以通過super.函數名獲取
可以通過super.函數名? ?第22行
?運行結果
? 重寫方法不能比被重寫方法有更嚴格的訪問權限:
我把public 改成private行不行? ? ?第21行
錯誤提示:Cannot reduce the visibility of the inherited method from Person
不能減除可視的等級
?如果我不寫呢?第21行
默認也是不行的
?那么如果是增加它的等級呢?
第8 行去掉public? ?第21行補回public
?把22行去掉
如果結果你看到System.out.println("子類打印name="+name);
而不是System.out.println("name="+name);
也可以認定為方法的重寫
?運行一下
?? 父類中的私有方法,不能被重寫
因為address是私有的屬性,所以先不打出來? ? ? ? 第27行
給人的感覺被重寫了
可是我的student繼承于person,可是這面顯示不能調用
錯誤提示:The method printAddr() from the type Student is not visible
他這面默認這個printAddr是父親的私有,即使你寫了一個自己的私有,他也不給你用
?
?哪怕你不寫
他也認定這個printAddr是父親的,你是不可見的
錯誤提示:The method printAddr() from the type Person is not visible
?那么如果改成不一樣的權限呢?
????????這個時候就可以用
因為在Java看來你的????????void printAddr(){
?? ??????????????????????????????????????????? ?System.out.println("私有方法");
?????????????????????????????????????????? ?}
跟父類的????????????????private void printAddr(){
?? ??? ?????????????????????????System.out.println("address="+address);
?????????????????????????????????? ?}
? ? 根本就不是重寫
因為父類私有的方法,對子類是不可見的,現在相當于添加了一個自己的方法? 第26,27行
既不是重寫,也不是重載,是自己添加了一個方法
?
?運行結果
?總結一下:
重寫和重載的區別:??
重寫必須必須具有相同的方法名稱、參數列表、返回值,重載只要方法名稱相同就是一個重載
重寫加一個public 你會發現是子類的打印? ? ? ? 第20行
運行結果?
?
?如果把他去掉的話,他就會調用父親的name=陳
從運行效果看,他就是重寫的一種方式
重寫可以增加它的訪問權限,但是也不一定,記得查閱資料
運行結果
?五、Java繼承之Object類
? ? ? ? Java中, 所有類都直接或間接繼承自java.lang.Object類
? ? ? ? ? ? ? ? ? ? ? ? 可以說Object是java中所有類祖先即根類
? ? ? ? Java中任何類都繼承了Object類中的方法,主要有
? ? ? ? ? ? ? ? ? ? ? ? toString()
? ? ? ? ? ? ? ? ? ? ? ? equals()
? ? ? ? ? ? ? ? ? ? ? ? hashcode()
? ? ? ? ? ? ? ? ? ? ? ? clone()
? ? ? ? ? ? ? ? ? ? ? ? getClass()
? ? ? ? ? ? ? ? ? ? ? ? finalize()
? ? Java中, 所有類都直接或間接繼承自java.lang.object類
? ? ? ? ? ? ? ? ? ? ? ? 可以說Object是java中所有類祖先即根類
我們學習Linux的時候,學習了根目錄,根一般來說是最頂層的目錄
那Object是根類,也就是所有類最頂層的類
? Java中任何類都繼承了object類中的方法
既然是祖先的話,他的子,它的孫,它的曾孫,都包含它的一些方法
用的多的是
????????????????????????? toString()
? ? ? ? ? ? ? ? ? ? ? ??????? equals()
新建一個工程,
看看函數p.toString輸出是什么
運行結果
jicheng.lizhaopeng.java.? ? ? ? 包名
Person
@659e0bfd? ? ? ? 地址
打印了Person的內存空間
這個to String從字面上的意思是轉化為字符串
這不是我們想看到的東西,我們轉化成字符串想要看到什么呢?
我們是不是可以把他的名字和屬性給他打出來
?我們可以用重寫的技術,對這個toString來重寫
默認是返回父親的to String? ?第16行,第17行
?我們不想讓他返回父類的toSting 我們可以這樣做
運行結果
默認的toStiring打印的是虛擬地址? ? ? ? ? 第31行
?然后我們用一下equals()? ? ? ? ?第33行
我們看到兩個名字和地址是完全一樣的
?運行結果
有點奇怪,按照我們c語言的開發,只要字符串跟里面的某一些屬性相等的話,就想要讓他覺得兩個結構體一樣
但他這邊比的還是地址
所以我們可以重寫一下equals
定義一個person p 然后把arg0強轉成person
我們在做一個判斷
如果里面的屬性的值相等的話,我們就判斷這兩個對象是相等的? ?第34行到36行? ? 第38到40行
?運行結果
在比較字符串的時候,java是比較靈活的,可以用兩個等號,
我們學習c的時候用strcmp,包括給字符串賦值的時候用strcpy
String? ?toString()
? ? ? ? 返回該對象的字符串描述信息。默認輸出的格式:
? ? ? ? ? ? ? ? 類名【字段值,字段值·· ···】
? ? ? ? 只要對象與一個字符串通過“+”連接,系統就會自動調用toString獲得對象的字符描述符
? ? ? ? 常被改寫:可以根據用戶的需求對其進行重寫
Boolean? ? equals()
? ? ? ? object類原始功能是實現判斷兩個對象是否具有相同的引用,要求判斷兩個對象狀態的相等值
六、Java繼承之綜合小練習
新建一個工程
?現在有個類要設置一下,肯定有個玩家? ? ? ? ?Play
play有什么特征呢?
昵稱,? ? ? ? name
等級,? ? ? ? duanwei
id號,? ? ????????? ? id
攻擊 ,? ? ? ? attack
武器? ? ? ? ? ? ? ? wapon
比如,我內部還有個武器,武器是不是要做一個武器的類
????????class Wapon
????????{
?????????????????? ?String name;? ? ? ? //武器是不是還有名字
?????????????????? ?void waponAttack()????????
?????????????????? ?{
?? ??????????????????? ?System.out.println("武器攻擊");
? ? ? ? ? ? ? ? ? ? ?}
????????}
????????
玩家攻擊的時候是不是調用武器攻擊,武器攻擊有很多種? ? ? ??
比如k98攻擊,繼承它并且重寫它
如果現在用我們學過的東西,不太夠寫,因為需要涉及到多態
?
?運行一下
因為他會調用38行的wapon.waponAttack();
wapon并沒有被賦值
那么我們p1.wapon = new Wapon();是不是就可以啦
?
運行結果
?其實可以把?? ?p1.wapon = new Wapon();
變成??????????p1.wapon = new koushui();
第49行就是我們要講的多態的概念
?
?運行結果
?在修改一下
?
?運行結果
這就是多態的概念? ? ? ? ? 第49行? ? ? ? 第52行
多態是在繼承的基礎上
我們的繼承體現在武器上,繼承的時候去重寫里面的方法
我們給p1.wapon初始化,按照以前的寫法是new Wapon,現在可以直接new koushui
因為Wapon包含了koushui 和K98,所以可以直接把你new出來的koushui 和K98的對象直接給這個wapon
七、java繼承之簡單工廠模式
?
?運行結果
總結
以上是生活随笔為你收集整理的Java:继承之super关键字,继承之私有权限,继承之方法重写,继承之object类,继承之简单工厂模式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 哪些银行可以办理etc 办理条件介绍
- 下一篇: Java:抽象方法和抽象类,抽象类应用模