繼承
繼承概述
多個類中存在相同屬性和行爲是,將這些內容抽取到單獨一個類中,那麼多個類無需再定義這些屬性和行爲,只要繼承那個類即可。
通過extends關鍵字可以實現類與類的繼承
格式:
class 子類名 extends 父類名 { }
單獨的這個類稱爲父類,基類或超類;這多個類可以稱爲子類或者派生類。
有了繼承以後,我們定義一個類時,可以在一個已經存在的類的基礎上,還可以定義自己的新成員
繼承的好處
提高了代碼的複用性
多個類的相同成員可以放到同一個類中
提高了代碼的維護性
如果功能代碼需要修改,修改一處即可
讓類與類之間產生了關係,是多態的前提
也是繼承的一個弊端:類的耦合性很強
開發的原則:低耦合,高內聚。
耦合:類與類的關係
內聚:自己完成某件功能的能力
Java中繼承的特點:
Java只支持單繼承,不支持多繼承。(有些語言支持多繼承,格式:extends 類1,類2,....)
Java支持多層繼承(繼承體系)
class A{}
class B extends A{}
class C extends B{}
(C可以調用B中方法也可以調用A中方法)
繼承的注意事項:
子類只能繼承父類所有非私有的成員(成員方法和成員變量)
子類不能繼承父類的構造方法,但可以通過super關鍵字去訪問父類構造方法
不要爲了部分功能而去繼承
繼承中成員變量的關係
子類中的成員變量和父類中的成員變量名稱一樣時,變量就近原則。
先查看子類方法的局部範圍找,有就使用,否則在子類的成員方法找,有就是用,否則在父類的成員範圍找。
super關鍵字
super的用法和this很像
super代表父類存儲空間的標識(可以理解未父類引用)
用法(this和super均可如下使用)
調用成員變量
this.成員變量 調用本類的成員變量
super.成員變量 調用父類的成員變量
調用構造變量
this(...) 調用本類的構造方法
super(...) 調用父類的構造方法
調用成員方法
this.成員方法 調用本類的成員方法
super.成員方法 調用父類的成員方法
繼承中構造方法的關係
子類中所有的構造方法默認都會訪問父類中空參數的構造方法
因爲子類會繼承父類中的數據,可能還會使用父類的數據,所以子類初始化之前,一定要先完成父類數據初始化
注意:子類每一個構造方法的第一條語句默認都是super();
如果父類中沒有無參構造方法,默認不會對父類成員變量進行初始化,解決方案:
1、在父類中加一個無參構造方法
2、通過使用super關鍵字去顯示的調用父類的帶參構造方法
3、子類通過使用this去調用本類的其他構造方法
子類一定要有一個去訪問了父類的構造方法,否則父類數據就沒有初始化
注意事項:
this(...)或super(...)必須出現在第一條語句上。
如果不是放在了第一條語句上,就可能對父類的數據進行了多次初始化
一個類的靜態代碼塊,構造代碼塊,構造方法的執行流程
靜態代碼塊>構造代碼塊>構造方法
靜態的內容是隨着類的加載而加載
靜態代碼塊的內容會優先執行
子類初始化之前先會進行父類的初始化
一個類的初始化過程
成員變量進行初始化
默認初始化
顯示初始化
構造方法初始化
繼承中成員方法的關係
如果子類中的方法和父類中的方法聲明一樣,通過子類調用方法,先找子類中看有沒有這個方法,有就使用;沒有再看父類中。(方法重寫)
方法重寫:子類中出現了和父類中方法一模一樣(方法名、參數列表、返回值類型)的方法。也被稱爲方法覆蓋、方法複寫。
使用特點:
如果方法名不同,就調用對應方法
如果方法名相同,最終使用的是子類自己的
方法重寫的應用:
當子類需要父類的功能,而功能主體子類有自己特有內容時,可以重寫父類中的方法,這樣即沿襲了父類的功能,又定義了子類特有的內容。
方法重寫的注意事項
父類中私有方法不能被重寫 (父類私有方法子類無法繼承 )
子類重寫父類方法時,訪問權限不能更低
父類靜態方法,子類也必須通過靜態方法進行重寫。
Override:方法重寫
Overload:方法重載
class Person{
private String name;
private int age;
public Person() {
}
public Person(String name,int age) {
this.name=name;
this.age=age;
}
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;
}
}
class Student2 extends Person{
public Student2() {
}
public Student2(String name,int age) {
super(name,age);
}
}
class Teacher extends Person{
public Teacher() {
}
public Teacher(String name,int age) {
super(name,age);
}
}
public class PersonTest {
public static void main(String[] args) {
Student2 s = new Student2();
s.setName("劉備");
s.setAge(25);
System.out.println(s.getName()+"---"+s.getAge());
Teacher ss = new Teacher("諸葛孔明",30);
System.out.println(ss.getName()+"---"+ss.getAge());
}
}
------------------------------------------------------------------------
結果:
劉備---25
諸葛孔明---30
class Animal{
private String name;
private int age;
private String color;
public Animal() {
}
public Animal(String name,int age, String color) {
this.name=name;
this.age=age;
this.color=color;
}
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;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public void eat() {
System.out.println("吃!");
}
}
class Cat extends Animal{
public Cat() {
}
public Cat(String name,int age,String color) {
super(name,age,color);
}
public void PlayGame(String name) {
System.out.println(name+"玩遊戲!");
}
}
class Dog extends Animal{
public Dog() {
}
public Dog(String name,int age,String color) {
super(name,age,color);
}
public void LookDoor(String name) {
System.out.println(name+"看門!");
}
}
public class CatDogtest {
public static void main(String[] args) {
Cat s = new Cat();
s.setName("花花");
s.setAge(2);
s.setColor("花色");
System.out.println(s.getName()+"---"+s.getAge()+"---"+s.getColor());
s.eat();
s.PlayGame("花花");
System.out.println("--------------");
Dog ss = new Dog("小黑",3,"黑色");
System.out.println(ss.getName()+"---"+ss.getAge()+"---"+ss.getColor());
ss.eat();
ss.LookDoor("小黑");
}
}
-----------------------------------------------------------------------------------------
結果:
花花---2---花色
吃!
花花玩遊戲!
--------------
小黑---3---黑色
吃!
小黑看門!