一、介紹
繼承是面向?qū)ο笞铒@著的一個特性肘交。繼承是從已有的類中派生出新的類玻孟,新的類能吸收已有類的數(shù)據(jù)屬性和行為唆缴,并能擴展新的能力。Java繼承是使用已存在的類的定義作為基礎(chǔ)建立新類的技術(shù)黍翎,新類的定義可以增加新的數(shù)據(jù)或新的功能面徽,也可以用父類的功能,但不能選擇性地繼承父類匣掸。這種技術(shù)使得復(fù)用以前的代碼非常容易趟紊,能夠大大縮短開發(fā)周期,降低開發(fā)費用碰酝。
在面向?qū)ο蟪绦蛟O(shè)計中運用繼承原則织阳,就是在每個由一般類和特殊類形成的一般——特殊結(jié)構(gòu)中,把一般類的對象實例和所有特殊類的對象實例都共同具有的屬性和操作一次性地在一般類中進行顯式的定義砰粹,在特殊類中不再重復(fù)地定義一般類中已經(jīng)定義的東西唧躲,但是在語義上,特殊類卻自動地碱璃、隱含地擁有它的一般類(以及所有更上層的一般類)中定義的屬性和操作弄痹。特殊類的對象擁有其一般類的全部或部分屬性與方法,稱作特殊類對一般類的繼承嵌器。
比如可以先定義一個類叫車肛真,車有以下屬性:車體大小,顏色爽航,方向盤蚓让,輪胎乾忱,而又由車這個類派生出轎車和卡車兩個類,為轎車添加一個小后備箱历极,而為卡車添加一個大貨箱窄瘟。
二、知識點介紹
1趟卸、繼承概念
2蹄葱、繼承的定義及使用格式
3、繼承注意事項
4锄列、方法重寫
三图云、上課對應(yīng)視頻的說明文檔
1、繼承概念
1.1邻邮、繼承概述
繼承是面向?qū)ο蟮暮诵奶匦钥⒖觯敲嫦驅(qū)ο蟮膶W(xué)習(xí)重點。同時繼承是代碼復(fù)用的重要方式筒严,可以表示類與類之間的關(guān)系丹泉,是所有面向?qū)ο笳Z言不可缺少的組成部分。
1.2萝风、繼承概念
當(dāng)一個類的屬性與行為均與現(xiàn)有類相似嘀掸,屬于現(xiàn)有類的一種時,這一個類可以定義為現(xiàn)有類的子類规惰。
或者換成相反的角度來看睬塌,如果多個類具有相同的屬性和行為,我們可以抽取出共性的內(nèi)容定義父類歇万,這時再創(chuàng)建相似的類時只要繼承父類即可揩晴。
子類擁有父類的所有屬性與方法,無需重新定義贪磺。并且可以直接使用非私有的父類成員硫兰。
從類與類之間的設(shè)計關(guān)系來看,子類必須屬于父類的一種時,才會繼承寒锚。
我們在完成一個龐大項目體系的時候劫映,都是將共性的內(nèi)容抽取出,后續(xù)構(gòu)建過程是從各種父類“向外”擴散的刹前。
下例展示了一個繼承關(guān)系
圖1-1 動物繼承關(guān)系圖
動物類可以有姓名泳赋、年齡的成員變量,可以有吃飯喇喉、睡覺的方法祖今。
所有貓科與犬科均有動物的成員變量與成員方法,且貓科與犬科均屬于動物,所以貓科與全科均可以繼承動物類千诬。
貓科可以在動物的基礎(chǔ)上再添加抓老鼠的方法
犬科可以在動物的基礎(chǔ)上再添加看門的方法
犬科與貓科仍可以繼續(xù)出現(xiàn)子類耍目,如波斯貓、巴厘貓徐绑、沙皮狗邪驮、斑點狗等,而其子類仍可以再出現(xiàn)該品種的特性泵三。
2耕捞、繼承定義及使用格式
2.1衔掸、繼承定義
class 子類 extends 父類{
//父類的非私有方法與屬性均繼承過來
}
如:
父類的定義:
class Person{
private String name;
public void eat(){
System.out.println(“吃飯”);
}
get/set方法
}
子類繼承父類的定義:
class Chinese extends Person{}
2.2烫幕、繼承使用
繼承關(guān)系的產(chǎn)生通常是為了定義出功能更為具體、更為強大的子類敞映。所以较曼,定義子類后,一般創(chuàng)建子類對象使用振愿。子類可以直接使用父類非私有的成員變量與成員方法
(注:如果成員變量沒有使用private修飾捷犹,則子類也可直接訪問。)
子類的使用:
class Test{
public static void main(String[] args) {
Chinese? c = new Chinese();
c.setName(“張大力”);
String name = c.getName();
System.out.println(name);//打印結(jié)果為張大力
c.eat();? //打印結(jié)果吃飯
}
3冕末、繼承注意事項
Java只支持單繼承萍歉,不支持多繼承。即只能有一個父類档桃。
父類可以繼續(xù)有父類枪孩。
所有類均有父類,只有Object類沒有父類藻肄。
在所有使用父類類型的地方均可以傳入其子類對象蔑舞。
/*
* Animal的類
* 屬性
*? ? ? ? name
*? ? ? ? age
* 行為
*? ? ? ? 吃
*? ? ? ? 睡
*/
public class Animal {
//成員變量
private String name;
private int age;
// //吃
// public abstract void eat(){
//? ? System.out.println(“吃”);
//? ? }
//睡
public void sleep(){
System.out.println("睡");
}
//-----------get/set-------------------
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
/*
*定義一個貓類
* 屬性
*? name?
*? age
*? kind
* 行為
*? 吃
*? 睡
*? 抓老鼠
*/
public class Cat extends Animal{
private String kind;
// @Override
// public void eat(){
//? System.out.println("貓吃魚");
// }
//貓?zhí)赜械墓δ? 抓老鼠
public void catchMouse(){
System.out.println("抓耗子");
}
public String getKind() {
return kind;
}
public void setKind(String kind) {
this.kind = kind;
}
}
/*
*定義一個狗類
* 屬性
*? name?
*? age
*? kind
* 行為
*? 吃
*? 睡
*? 看門
*/
public class Dog extends Animal{
private String kind;
// @Override
// public void eat(){
//? System.out.println("狗吃肉");
// }
//狗特有功能? 看門
public void lookDoor(){
System.out.println("看門");
}
public String getKind() {
return kind;
}
public void setKind(String kind) {
this.kind = kind;
}
}
/*
* 自定義類型 家
*
*? 地址
*
* 行為
*? 在家吃飯
*/
public class Home {
private String address;
//動物在家吃飯
//在所有使用父類類型的地方均可以傳入其子類對象。
public void eatAtHome(Animal a){
//調(diào)用Animal的eat方法
//a.eat();?
}
//狗在在家吃飯
// public void eatAtHome(Dog dog){
//? System.out.println("狗在家吃了");
//? //調(diào)用狗的eat方法
//? dog.eat();
// }
//貓在家吃飯
// public void eatAtHome(Cat cat){
//? System.out.println("貓在假吃了");
//? //調(diào)用貓的eat方法
//? cat.eat();
// }
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
/**
* 測試家類
*/
public class Test {
public static void main(String[] args) {
//? 創(chuàng)建Home對象
Home home = new? Home();
//? Animal a = new Animal();?
//? home.eatAtHome(a);?
//在所有使用父類類型的地方均可以傳入其子類對象嘹屯。
Dog d = new Dog();
home.eatAtHome(d);
Cat c = new Cat();
home.eatAtHome(c);?
}
}
4攻询、方法重寫
4.1、方法重寫概念
當(dāng)子類繼承父類后州弟,擁有了父類的成員并可以直接調(diào)用父類非私有方法钧栖。如果子類認為父類提供的方法不夠強大,子類可以按照子類自身的邏輯重新定義繼承過來的父類方法婆翔,這個重新定義一個方法的過程叫做方法重寫拯杠。
(注:在學(xué)習(xí)完多態(tài)和抽象類后我們會對方法重寫有更深的理解)
4.2、方法重寫格式
子類中定義與父類一樣的方法便將父類的方法重寫了浙滤。此時阴挣,當(dāng)創(chuàng)建子類對象,調(diào)用方法時纺腊,會調(diào)用子類重寫后的方法畔咧。如:
子類中定義與父類一樣的方法聲明即是方法重寫茎芭。
如:
父類定義:
public class Person{
private String name;
public void eat(){
System.out.println(“吃飯”);
}
get/set
}
子類定義:
public class Chinese extends Person{
@override //@override是用于強制規(guī)定當(dāng)前定義的方法一定為重寫的方法
public void eat() {
System.out.println(“按照中國的習(xí)慣,使用筷子吃”);
}
}
子類的使用:
public class Test{
public static void main(String[] args) {
Chinese? c = new Chinese();
c.setName(“張大力”);? //父類繼承方法直接調(diào)用
String name = c.getName(); //父類繼承方法直接調(diào)用
System.out.println(name); //打印結(jié)果為張大力
c.eat();? //方法重寫后調(diào)用的為重寫后的方法
//打印結(jié)果:按照中國的習(xí)慣誓沸,使用筷子吃
}
}
/**
* 自定義類型? 人類
*
*? ? 姓名? 年齡
*/
public class Person {
String address;
private String name;
private int age;
public void eat(){
System.out.println("吃");? ?
}
public void sleep(){
System.out.println("睡");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
/*
* 定義類型? 學(xué)生類
*
* 姓名? 年齡
*
* 繼承
*? 概念1? 當(dāng)定義一個類時梅桩,發(fā)現(xiàn)現(xiàn)有類與要定義的類類似,并且要定義的類屬于現(xiàn)有類的一種時拜隧,
*? 就可以將這個類定義為現(xiàn)有類的子類
*?
*? 子類擁有父類的所有屬性與方法宿百,無需重新定義。并且可以直接使用非私有的父類成員洪添。
*?
*? 父類私用的成員變量? 可以使用get/set方法 訪問
*? 父類私有的方法? 沒有辦法直接方法? 雖然繼承了 但是相當(dāng)于沒有
*? ?
*? 子類可以有自己特有的屬性和方法
*?
*? 方法重寫
*? ? 子類繼承父類后垦页,可以直接使用父類的非私有成員,但是如果覺得父類的成員方法不夠強大干奢,子類可以按照自身的邏輯
*? ? 將繼承過來的父類方法痊焊,進行重寫(方法重寫,方法復(fù)寫忿峻,方法覆蓋)
*?
*? 可以使用@Override來驗證你的方法是不是重寫方法薄啥。
*/
public class Student extends Person{
private String number;
public void method(){
System.out.println(address);
System.out.println(getName());
}
//重寫父類eat方法
@Override
public void eat(){
System.out.println("學(xué)生吃學(xué)生套餐");
}
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
}
/*
* 測試繼承后的Studnet
*/
public class Test {
public static void main(String[] args) {
//創(chuàng)建Studnet對象
Student s = new Student();
s.setName("柳柳");
s.setNumber("0900112");
s.eat();
//? s.sleep();
String name = s.getName();
System.out.println(name);
System.out.println(s.getNumber());
System.out.println("-----------------");
//子類調(diào)用自己特有的方法
s.method();?
}
}
4.3、Java中方法重寫規(guī)則
子類重寫方法時逛尚,在聲明前加@Override可檢測該方法是否為重寫的方法
訪問權(quán)限相同或子類方法訪問權(quán)限更大(訪問權(quán)限順序public>默認)
class Fu{
void show(){}
public void method(){}
}
class Zi extends Fu{
public void show(){}? //編譯運行沒問題
void method(){}? ? ? //編譯錯誤
}
方法名稱必須相同
參數(shù)列表必須相同
返回值為基本類型時必須相同
返回值為引用類型時相同或子類小(了解)
/*
* 方法重寫的注意事項
*? 子類重寫方法時垄惧,在聲明前加@Override可檢測該方法是否為重寫的方法
*? 訪問權(quán)限相同或子類方法訪問權(quán)限更大(訪問權(quán)限順序public>默認)
*? 方法名稱必須相同
*? 參數(shù)列表必須相同
*? 返回值為基本類型時必須相同
*? 返回值為引用類型時相同或子類小(了解)
*/
public class Fu {
public void method(){
System.out.println(" 父類方法");
}
public int sum(){
return 0;
}
public Person get(){
return null;
}
}
public class Zi extends Fu{
//訪問權(quán)限相同或子類方法訪問權(quán)限更大(訪問權(quán)限順序public>默認)
@Override
public void method(){
System.out.println("子類方法");
}
//返回值為基本類型時必須相同
@Override
public int sum(){
return 100;
}
//返回值為引用類型時相同或子類小(了解)
@Override
public Student get(){
return null;
}
}