第8章 面向?qū)ο?/h1>
8.1 Java 繼承
繼承的概念:指子類繼承父類的特征和行為,使得子類對(duì)象(實(shí)例)具有父類的實(shí)例域和方法,或子類從父類繼承方法,使得子類具有父類相同的行為。
image.png
- 兔子和羊?qū)儆谑巢輨?dòng)物類,獅子和豹屬于食肉動(dòng)物類。
- 食草動(dòng)物和食肉動(dòng)物屬于動(dòng)物類。
- 繼承關(guān)系屬于:is-a,父類更通用,子類更具體。
- 雖然食草動(dòng)物的食肉動(dòng)物都屬于動(dòng)物,但是兩者的屬性和行為上有差別,所以子類會(huì)具有父類的一般特性也會(huì)具有自身的特性。
類的繼承格式
繼承的概念:指子類繼承父類的特征和行為,使得子類對(duì)象(實(shí)例)具有父類的實(shí)例域和方法,或子類從父類繼承方法,使得子類具有父類相同的行為。

在java中通過 extends 關(guān)鍵字可以申明一個(gè)類是從另一個(gè)類繼承而來的,一股形式如下:
class 父類 {
}
class 子類 extends 父類 {
}
為什么需要繼承
動(dòng)物實(shí)例:企鵝和老鼠。
- 企鵝:屬性( 姓名,id ),方法( 吃,睡,自我介紹 )
- 老鼠:屬性(姓名,id ),方法( 吃,睡,自我介紹 )
企鵝類
public class Penguin {
private String name;
private String id;
public Penguin( String myName,int myid ){
name = myName;
id = myid;
}
public void eat(){
System.out.println( name + " 正在吃");
}
public void sleep(){
System.out.println( name + " 正在睡");
}
public void introduction(){
System.out.println( " 大家好!我是 " + id + " 號(hào)" + name + " 。");
}
}
老鼠類
public class Mouse {
private String name;
private int id;
public Mouse(String myName, int myid) {
name = myName;
id = myid;
}
public void eat(){
System.out.println(name+"正在吃");
}
public void sleep(){
System.out.println(name+"正在睡");
}
public void introduction() {
System.out.println("大家好!我是" + id + "號(hào)" + name + ".");
}
}
從企鵝和老鼠兩個(gè)類來看,代碼存在重復(fù),且維護(hù)性不高。繼承就能排上用場了
公共父類
public class Animal {
private String name;
private String id;
public Animal( String myName,int myid ){
name = myName;
id = myid;
}
public void eat(){
System.out.println(name+"正在吃");
}
public void sleep(){
System.out.println(name+"正在睡");
}
public void introduction() {
System.out.println("大家好!我是" + id + "號(hào)" + name + ".");
}
}
企鵝類
public class Penguin extends Animal {
public Penguin(String myName,int myid){
super(myName,myid);
}
}
企老鼠
public class Mouse extends Animal {
public Mouse(String myName,int myid){
super(myName,myid);
}
}

繼承在的特性
- 子類擁有父類非 private 的屬性 方法。
- 子類可買擁有自己屬性和方法,即子類可以對(duì)父類進(jìn)行擴(kuò)展。
- 子類可以用自己的方式實(shí)現(xiàn)父類的方法。
繼承關(guān)鍵字 extends 和implements
extends 關(guān)鍵字
在Java中,類的繼承是單一繼承,也就是說,一個(gè)子類只能擁有一個(gè)父類,所以 extend 只能繼承一個(gè)類。
public class Animal {
private String name;
private int id;
public Animal(String myName, String myid) {
//初始化屬性值
}
public void eat() { //吃東西方法的具體實(shí)現(xiàn) }
public void sleep() { //睡覺方法的具體實(shí)現(xiàn) }
}
public class Penguin extends Animal{
}
implements 關(guān)鍵字
保用implements關(guān)鍵字可以變相的使Java具有多繼承的特性,使用范圍為類繼承接口的情況,可以同時(shí)繼承多個(gè)接口(接口跟接口之間采用逗號(hào)分隔)。
public interface A {
public void eat();
public void sleep();
}
public interface B {
public void show();
}
public class C implements A,B {
}
super 與 this 關(guān)鍵字
super關(guān)鍵字:我們可以通過關(guān)鍵字來實(shí)現(xiàn)對(duì)父類成員的訪問,用來引用當(dāng)前對(duì)象的父類。
this關(guān)鍵字:指向自己的引用。
實(shí)例
class Animal {
void eat() {
System.out.println("animal : eat");
}
}
class Dog extends Animal {
void eat() {
System.out.println("dog : eat");
}
void eatTest() {
this.eat(); // this 調(diào)用自己的方法
super.eat(); // super 調(diào)用父類方法
}
}
public class Test {
public static void main(String[] args) {
Animal a = new Animal();
a.eat();
Dog d = new Dog();
d.eatTest();
}
}
final 關(guān)鍵字
final關(guān)鍵字聲明類可以把類定義不能繼承的,即最終類;或者用于修飾方法,該方法不能被子類重寫。

注:實(shí)例變量也可以被定義為 final,被定義為 final 的變量不能被修改。被聲明為 final 類的方法自動(dòng)地聲明為 final,但是實(shí)例變量并不是 final
構(gòu)造器
子類是不繼承父類的構(gòu)造器(構(gòu)造方法或者構(gòu)造函數(shù))的,它只是調(diào)用(隱式或顯式)。如果 父類的構(gòu)造器帶有參數(shù),則必須在子類構(gòu)造器中顯式地通過 super 關(guān)鍵字調(diào)用父類的構(gòu)造器并配以適當(dāng)?shù)膮?shù)列表。如果父類構(gòu)造器沒有參數(shù),則在子類的構(gòu)造器中不需要使用 super 關(guān)鍵字調(diào)用父類構(gòu)造器,系統(tǒng)會(huì)自動(dòng)調(diào)用父類的無參構(gòu)造器。
實(shí)例
class SuperClass {
private int n;
SuperClass(){
System.out.println("SuperClass()");
}
SuperClass(int n) {
System.out.println("SuperClass(int n)");
this.n = n;
}
}
// SubClass 類繼承
class SubClass extends SuperClass{
private int n;
SubClass(){ // 自動(dòng)調(diào)用父類的無參數(shù)構(gòu)造器
System.out.println("SubClass");
}
public SubClass(int n){
super(300); // 調(diào)用父類中帶有參數(shù)的構(gòu)造器
System.out.println("SubClass(int n):"+n);
this.n = n;
}
}
// SubClas2 類繼承
class SubClass2 extends SuperClass{
private int n;
SubClass2(){
super(300); // 調(diào)用父類中帶有參數(shù)的構(gòu)造器
System.out.println("SubClass2");
}
public SubClass2(int n){ // 自動(dòng)調(diào)用父類的無參數(shù)構(gòu)造器
System.out.println("SubClass2(int n):"+n);
this.n = n;
}
}
public class TestSuperSub{
public static void main (String args[]){
System.out.println("------SubClass 類繼承------");
SubClass sc1 = new SubClass();
SubClass sc2 = new SubClass(100);
System.out.println("------SubClass2 類繼承------");
SubClass2 sc3 = new SubClass2();
SubClass2 sc4 = new SubClass2(200);
}
}