繼承的概念、特點,繼承中方法覆蓋的應用,this和super的使用方法
8.2 繼承
8.2.1 生活中的繼承
- 生活中的“繼承”是施方的一種贈與,受方的一中獲得;
- 將一方所擁有的東西給予另一方;
8.2.2 程序中的繼承
- 程序中的繼承,是類與類之間特徵和行爲的一種贈與或獲得;
- 兩個類之間的繼承關係,必須滿足“is a”的關係;
8.2.3 父類的選擇
- 現實生活中,很多類別之間都存在着繼承關係,都滿足“is a”的關係;
- 狗是一種動物,狗是一種生物,狗是一種物質;
- 多個類別都可作爲“狗”的父類,需要從中選擇出最合適的父類;
- 功能越精細,重合點越多,越接近直接父類;
- 功能越粗略,重合點越少,越接近Object類;(萬物皆對象的概念)
8.2.4 父類的抽取
- 可根據程序需要使用到多個具體類,進行共性抽取,進而定義父類;
8.2.5 繼承
- 語法:
class 子類 extends 父類{} //定義子類時,顯示繼承父類 - 應用:
產生繼承關係之後,子類可以使用父類中的屬性和方法,也可定義子類獨有的屬性和方法; - 好處:
既提高代碼的複用性,又提高代碼的可擴展性;
public class TestExtends {
public static void main(String[] args) {
Dog dog = new Dog();
dog.breed = "哈士奇";//繼承自父類
dog.age = 3;//繼承自父類
dog.sex = "公";//繼承自父類
dog.furColor = "黑白";//子類獨有
dog.eat();//繼承自父類
dog.run();//子類獨有
}
}
//父類
class Animal{
String breed;//品種
int age;//年齡
String sex;//性別
public void eat() {}
public void sleep() {}
}
class Dog extends Animal{//完成繼承父類
String furColor;//毛色
public void run() {}
}
public class TestExpents2 {
public static void main(String[] args) {
Car car = new Car();
car.type = "小汽車";
car.price = 1000000D;
car.speed = 120;
car.brand = "保時捷";
car.run();
Bus bus = new Bus();
bus.type = "公交車";
bus.price = 1500000D;
bus.speed = 60;
bus.seatNum = 20;
bus.run();
}
}
//交通工具類
class Vehicle{
String type;//類型
double price;//價格
int speed;//速度
public void run() {
System.out.println("一輛"+this.type+"以"+this.speed+"/h的速度行駛中。。。");
}
}
class Car extends Vehicle{
String brand;//品牌
}
class Bus extends Vehicle{
int seatNum;//座位數
}
8.2.6 繼承的特點
- Java爲單繼承,一個類只能有一個父類,但可以多級繼承,屬性和方法逐級疊加;
8.2.7 不可繼承
- 構造方法:
類中的構造方法,只負責創建本類對象,不可繼承; - private修飾的屬性和方法:
訪問修飾符的一種,僅本類可見; - 父子類不再同一個package中時,default修飾的屬性和方法:
訪問修飾符的一種,僅同包可見;
8.2.8 訪問修飾符
- | 本類 | 同包 | 非同包子類 | 其他 |
---|---|---|---|---|
private | √ | × | × | × |
default | √ | √ | × | × |
protected | √ | √ | √ | × |
public | √ | √ | √ | √ |
8.3 方法的覆蓋
8.3.1 爲什麼要方法的覆蓋
- 思考:子類是否可以定義和父類相同的方法?
- 思考:爲什麼需要在子類中定義和父類相同的方法?
- 分析:當父類提供的方法無法滿足子類需求時,可在子類中定義和父類相同的方法進行覆蓋;
8.3.2 方法的覆蓋的特點
-
方法覆蓋原則:
方法名稱、參數列表、返回值類型必須與父類相同;
訪問修飾符可與父類相同或是比父類更寬泛; -
方法覆蓋的執行:
子類覆蓋父類方法後,調用時優先執行子類覆蓋後的方法;
public class TestOverride {
public static void main(String[] args) {
Dog2 dog = new Dog2();
dog.eat();//狗在喫骨頭
Cat cat = new Cat();
cat.eat();//動物在喫
}
}
class Animal2{
String breed;//品種
int age;
String sex;
public void eat() {
System.out.println("動物在喫");
}
public void sleep() {
System.out.println("動物在睡");
}
}
class Dog2 extends Animal2{
String furColor;//毛色
//子類中定義和父類相同的方法進行覆蓋
public void eat() {
System.out.println("狗在喫骨頭");
}
public void run() {
}
}
class Cat extends Animal2{
}
8.3.3 super關鍵字
- 在子類中,可直接訪問從父類繼承到的屬性和方法,但如果父子類的屬性或方法存在重名(屬性遮蔽、方法覆蓋)時、需要加以區分,纔可專項訪問;
public class TestSuperKeyword {
public static void main(String[] args) {
B b = new B();
b.upload();
b.print();
}
}
class A{
int value = 10;
public void upload(){
System.out.println("父類代碼");
//上傳文件的100行代碼
}
}
class B extends A{
int value = 20;//父子類的同名屬性不存在覆蓋關係,兩塊空間同時存在(子類遮蔽父類屬性),需使用不同前綴進行訪問
public void upload() { //super關鍵字可在子類訪問父類的方法
super.upload();//上傳文件的100行代碼
System.out.println("子類添加的代碼");
//修改文件名稱的一行代碼
} //使用“super.”的形式訪問父類的方法,進而完成在子類中的複用
//再疊加額外的功能代碼,組成新的功能
public void print() {
int value = 30;
System.out.println(value);//方法內的value
System.out.println(this.value);//子類屬性的value
System.out.println(super.value);//父類屬性的value
}
}
8.3.6 繼承中的對象的創建
- 在具有繼承關係的對象創建中,構建子類對象會先構建父類對象;
- 由父類的共性內容,疊加子類的獨有內容,組合成完整的子類對象;
class Father{
int a;
int b;
public void m1(){}
}
class Son extends Father{//子類持有的屬性和 方法:int a 、int b、int c、m1()、m2()
int c;
public void m1(){}
}
8.3.7 繼承後的對象構建過程
8.3.8 super調用父類的構造方法
public class TestSuperKeyword2 {
public static void main(String[] args) {
new C();
new B1();
new B1(10);
}
}
class A1{
public A1() {
System.out.println("A()");
}
public A1(int vlaue) {
System.out.println("A(int value)");
}
}
class B1 extends A1{
public B1() {
super();//super():表示調用父類無參的構造方法。如果沒有書寫,隱式存在於子類構造方法的首行
System.out.println("B()");
}
public B1(int value) {
super(value);//super(實參):表示調用父類有參的構造方法
System.out.println("B(int value)");
}
}
class C extends B1{
public C() {
super();//super():表示調用父類無參的構造方法
System.out.println("C()");
}
}
8.3.9 this和super
public class TestSuperKeyword3 {
public static void main(String[] args) {
new B2(10);
}
}
class A2{
public A2() {
System.out.println("A-無參構造");
}
public A2(int value) {
System.out.println("A-有參構造");
}
}
class B2 extends A2{
public B2() {
super();
System.out.println("B-無參構造");
}
public B2(int value) {
this();//super();
System.out.println("B-有參構造");
}
}
- this或super使用在構造方法中時,都要求在首行
- 當子類構造中使用了this()或this(實參),即不可再同時書寫super()或super(實參),會由this()執行的構造方法完成super()的調用;
8.3.10 總結
-
super關鍵字的第一種用法:
在子類的方法中使用“super.”的形式訪問父類的書寫和方法;
例如:super.父類書寫、super.父類方法(); -
super關鍵字的第二種用法:
在子類的構造方法的首行,使用“super()”或“super(實參)”,調用父類構造方法。 -
注意:
如果子類構造方法中,沒有顯示定義super()或super(實參),則默認提供super();
同一個子類構造方法中,super()、this()不可同時存在。