1.1、繼承概念
將對象的共性抽取出來。提取出一個單獨的類。
繼承使用復用以前的代碼非常容易,能夠大大的縮短開發周期,降低開發成本,同時增加程序的易維護性
繼承使重一個類A能夠直接使用另外一個類B的屬性和方法的一種途徑
類A可以有自己的屬性和方法通過 extends 關鍵字讓類與類之間產生繼承關系。
讓類和類之間產生了關系,有了這個關系,才有了多態的特性。
注意:千萬不要為了獲取其他類的功能,簡化代碼而繼承。
必須是類與類之間有所屬關系才可以繼承,所屬關系是 is a.的關系
1.2、繼承的實現
類的繼承格式
package com.study.day07.person;/** * 父類 * @author denny * */public class Person { /** * name=姓名 * age=年齡 * 都是私有的 */ private String name; private int age; /** * 無參數構造方法 */ public Person() { System.out.println("父類無參數的構造方法"); } /** * 有參數構造方法 * @param name=姓名 * @param age=年齡 */ public Person(String name, int age) { this.name = name; this.age = age; System.out.println("父類有參數的構造方法"); } /** * 顯示信息方法 */ public void show(){ System.out.println("父類show方法"); System.out.println("姓名: "+this.name+" /n年齡: "+this.age); } /** * getterXxx和setterXxx方法 * @return */ 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; } }
子類
package com.study.day07.person;/** * 學生類繼承父類 * @author denny * */public class Student extends Person { /** * gender=性別 * 子類特有的屬性 */ private String gender; /** * 子類無參數構造方法 */ public Student() { super();//使用父類的構造方法 System.out.println("子類無參數構造方法"); } public Student(String name,int age,String gender) { /* * 調用父類有參數的構造方法 */ super(name,age); this.gender = gender; System.out.println("子類有參數構造方法"); } public String getGender() { return gender; } public void setGender(String gender) { this.gender = gender; } /** * 重寫父類的方法 */ @Override public void show(){ super.show(); //調用父類的方法, System.out.println("子類show方法"); System.out.println("性別: "+this.gender); //子類自己的方法體 } }
測試類
package com.study.day07.person;import com.study.day07.person.Person;public class Test { public static void main(String[] args) { Person s=new Student("張三",20,"男"); s.show(); }}
結果:
父類有參數的構造方法子類有參數構造方法父類show方法姓名: 張三 年齡: 20子類show方法性別: 男
在子類構造函數執行時,發現父類構造函數也運行了。
原因:在子類的構造函數中,第一行有一個默認的隱式語句:super();
1.4、方法重寫
上例中子類show()實現的對父類show()方法的重寫.
/** * 重寫父類的方法 */ @Override public void show(){ super.show(); //調用父類的方法, System.out.println("子類show方法"); System.out.println("性別: "+this.gender); //子類自己的方法體 }
在子類覆蓋方法中,繼續使用父類的方法可以通過super.函數名獲取 ,super.變量名
什么時候使用覆蓋操作?
當子類需要父類的功能,而功能主體子類有自己特有內容時,可以復寫父類中的方法,這樣,即沿襲了父類的功能,又定義了子類特有的內容。
注意:
1、父類中的私有方法不可以被覆蓋。
2、父類為static的方法無法覆蓋。
3、覆蓋時,子類方法權限一定要大于等于父類方法權限。
1.5、子類的實例化過程
final可以修飾類,方法,變量。
final修飾的類不可以被繼承。
final修飾的方法不可以被覆蓋。
final修飾的變量是一個常量,只能被賦值一次。
為什么要用final修飾變量,其實,在程序中如果一個數據是固定的。那么直接使用這個數據就可以了,但是這種閱讀性差,所以應該給數據起個名稱。而且這個變量名稱的值不能變化,所以加上final固定。
寫法規范:常量所有字母都大寫,多個單詞,中間用_連接。
/*final 修飾的變量是常量不可更改其值*/class FinalDemo{ public static void main(String [] args){ final int x=5; x=4; System.out.println("x="+x); }}
結果:
3.1、抽象類概述
使用關鍵字abstract 來修飾
抽象定義:
抽象就是從多個事物中將共性的、本質的內容抽取出來。
例如:學生和老師都是人,人類就是抽象出來的共性。
抽象類:使用abstract 修飾。
抽象方法:Java中可以定義沒有方法體的方法,該方法的具體實現由子類完成,該方法稱為抽象方法,包含抽象方法的類就是抽象類。使用abstract來修飾
3.2、抽象類特點
抽象類和抽象方法必須用abstract關鍵字來修飾。
抽象方法只有方法聲明,沒有方法體,定義在抽象類中。
格式:修飾符 abstract 返回值類型 函數名(參數列表) ;
抽象類不可以被實例化,也就是不可以用new創建對象。
原因如下:
1. 抽象類是具體事物抽取出來的,本身是不具體的,沒有對應的實例。例如:犬科是一個抽象的概念,真正存在的是狼和狗。
2. 而且抽象類即使創建了對象,調用抽象方法也沒有意義。
3. 抽象類通過其子類實例化,而子類需要覆蓋掉抽象類中所有的抽象方法后才可以創建對象,否則該子類也是抽象類。
示例:
package com.day08.abstrac.demo1;/** * 定義人類抽象類 * @author denny * */public abstract class Person { /** * 定義屬性 * name=姓名 * age=年齡 * gender=性別 */ private String name; private int age; private String gender; /** * 抽象方法 */ public abstract void life(); //生活方法 /** * getter和setter方法 * @return */ 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 getGender() { return gender; } public void setGender(String gender) { this.gender = gender; } }
子類:
package com.day08.abstrac.demo1;/** * 老師類繼承人類抽象類 * 必須實現人類中的抽象方法 * 如果不實現老師類必須是抽象類 * @author denny * */public class Teacher extends Person { @Override public void life() { System.out.println("教師的生活就是教學!"); }}
3.3、抽象類相關問題
抽象類中是否有構造函數?
答:有,用于給子類對象進行初始化。
抽象關鍵字abstract不可以和哪些關鍵字共存?
答:private、static、final。
抽象類中可不可以沒有抽象方法?
答:可以,但是很少見。目的就是不讓該類創建對象,AWT的適配器對象就是這種類。通常這個類中的方法有方法體,但是卻沒有內容。
3.4、抽象類和一般類的區別?
相同點:
抽象類和一般類都是用來描述事物的,都在內部定義了成員。
區別:
抽象類不可以被實例化,一般類可以被實例化
抽象類可以有抽象方法和一般方法,一般類只能有一般的方法
抽象類描述事物的信息有可能不足。一般類有足夠的信息描述事物。
抽象類一定是個父類嗎?
答:是的,因為需要子類覆蓋其方法后才可以對子類實例化。
4.1、接口定義
4.2、接口的實現
類要實現接口要使用implements關鍵字
格式 class 類名 implements 接口名
1.實現接口時,實現接口中的所有方法
2.
示例:
分別定義接口鳥的叫和攻擊方法都是抽象的
package com.day08.interfac.demo1;/** * 攻擊接口 * @author denny * */public interface BirdAttack { /** * 攻擊的方法 * 沒有方法體 */ public void attack(); }
package com.day08.interfac.demo1;/** * 叫聲的接口 * @author denny * */public interface BirdShout { /** * 叫的方法 * 沒有方法體 */ public void shout();}
火箭鳥
package com.day08.interfac.demo1;/** * 火箭鳥 * @author denny *攻擊方式:火箭攻擊 *實現了攻擊的接口和叫的接口,所有要重寫攻擊接口中的叫方法和攻擊方法 *接口可以實現多個,但繼承只能有一個 * */public class FireBird implements BirdAttack,BirdShout{ @Override public void shout() { System.out.println("火箭鳥喳喳叫!"); } @Override public void attack() { System.out.println("火箭鳥發射火箭弾攻擊!"); }}
胖子鳥
package com.day08.interfac.demo1;/** * 胖子鳥 * @author denny * 叫聲:唧唧叫 * 沒有攻擊,所以不需要實現攻擊的接口 * */public class FatBird implements BirdShout { @Override public void shout() { System.out.println("胖子鳥唧唧叫!"); } }
測試類
package com.day08.interfac.demo1;public class BirdTest { public static void main(String[] args) { //創建胖子鳥對象,并調用相應的方法 FatBird fatBird=new FatBird(); fatBird.shout(); //創建火箭鳥對象,并調用相應的方法 FireBird fireBird=new FireBird(); fireBird.shout(); fireBird.attack(); }}
結果
胖子鳥唧唧叫!火箭鳥喳喳叫!火箭鳥發射火箭弾攻擊!
以上例子中,實現的,行為和類的分離,需要哪個就實現哪個接口,沒有就不要實現
接口的出現將“多繼承”通過另一種形式體現出來,即“多實現”。
java將多繼承機制進行改良,在java中變成了多實現,一個類可以實現多個接口。
接口的出現避免了單繼承的局限性。
4.3、抽象類和接口
相同點:
抽象類和接口都不能被實例化
都是不斷向上抽取而來的。
區別:
1. 抽象類需要被繼承(extends),而且只能單繼承。
接口需要被實現,而且可以多實現。(implements)
2. 抽象類中可以定義抽象方法和非抽象方法,子類繼承后,可以直接使用非抽象方法。
接口中只能定義抽象方法,必須由子類去實現。
3. 抽象類的繼承,是is a關系,定義該體系的基本共性內容。
接口的實現是like a關系。
新聞熱點
疑難解答