學習Java第十三天--面向對象三大特性之繼承

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()不可同時存在。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章