今日內容介紹
一、繼承
二、抽象類
三、綜合案例---員工類系列定義java
*A:繼承的概念 *a:繼承描述的是事物之間的所屬關係,經過繼承可使多種事物之間造成一種關係體系 *b:在Java中,類的繼承是指在一個現有類的基礎上去構建一個新的類, 構建出來的新類被稱做子類,現有類被稱做父類 *B:繼承關係的子類特色 *a:子類會自動擁有父類全部非private修飾的屬性和方法
*A:繼承的格式 class 子類 extends 父類 {} *B:僱員(Employee)與研發部員工(Developer)案例: *cn.itcast.demo01包下: *Employee.java: /* * 定義員工類Employee */ class Employee { String name; // 定義name屬性 public void work() {// 定義員工的工做方法 System.out.println("全力以赴地工做"); } } *Developer.java: /* * 定義研發部員工類Developer 繼承 員工類Employee * 繼承了父類中全部非private修飾的成員變量 */ class Developer extends Employee { // 定義一個打印name的方法 public void printName() { System.out.println("name=" + name); } } *測試員工類與研發部員工類: /* * 定義測試類 */ public class Example01 { public static void main(String[] args) { Developer d = new Developer(); // 建立一個研發部員工類對象 d.name = "小明"; // 爲該員工類的name屬性進行賦值 d.printName(); // 調用該員工的printName()方法 d.work(); // 調用Developer類繼承來的work()方法 } } *經過子類對象既能夠調用自身的非private修飾的成員,也能夠調用父類的非private修飾的成員
*A:繼承的好處: *一、繼承的出現提升了代碼的複用性,提升軟件開發效率。 *二、繼承的出現讓類與類之間產生了關係,提供了多態的前提。
*A:繼承的注意事項 *a:在Java中,類只支持單繼承,不容許多繼承,也就是說一個類只能有一個直接父類,例以下面這種狀況是不合法的。 class A{} class B{} class C extends A,B{} // C類不能夠同時繼承A類和B類 假如支持多繼承例如: class A{ int a=3; public void method(){ } } class B{ int a=5; public void method(){ } } class C extends A,B{ } class Demo{ public static void main(String[] args){ C c=new C(); System.out.println(c.a);//究竟是調用A的仍是B的成員變量??沒法肯定 c.method();//究竟是調用A的仍是B的成員方法??沒法肯定 } } *b:多個類能夠繼承一個父類,例以下面這種狀況是容許的(就像你爹能夠多個兒子,可是這些兒子都只有一個爹) class A{} class B extends A{} class C extends A{} // 類B和類C均可以繼承類A *c:在Java中,多層繼承是能夠的, 即一個類的父類能夠再去繼承另外的父類, 例如C類繼承自B類,而B類又能夠去繼承A類,這時,C類也可稱做A類的子類。下面這種狀況是容許的。 class A{} class B extends A{} // 類B繼承類A,類B是類A的子類 class C extends B{} // 類C繼承類B,類C是類B的子類,同時也是類A的子類 *d:在Java中,子類和父類是一種相對概念, 也就是說一個類是某個類父類的同時,也能夠是另外一個類的子類。 例如上面的這種狀況中,B類是A類的子類,同時又是C類的父類。
*A:繼承的體系: 動物(吃) | ------------------------- | | 貓科動物(吃,胎生) 爬行動物(吃,卵生) | | ------------------------------- ----------------- | | | | 貓(吃,抓老鼠,胎生) 虎(吃,領地,胎生) 蛇(吃,冬眠,卵生) 鱷魚(吃,潛水,卵生) *a:動物體系是對每一個具體事物共性的抽取,子類的共性抽取造成父類 *b:父類:具備全部子類的共性內容 子類:不但有共性還有自身特有的內容 *c:整個繼承體系,越向上越抽象,越向下越具體
A:繼承後子類父類成員變量的特色 a:子類的對象調用成員變量的時候,子類本身有,使用子類,子類本身沒有調用的父類 class Fu{ //Fu中的成員變量。 int num = 5; } class Zi extends Fu{ //Zi中的成員變量 int num2 = 6; //Zi中的成員方法 public void show() { //訪問父類中的num System.out.println("Fu num="+num); //訪問子類中的num2 System.out.println("Zi num2="+num2); } } class Demo{ public static void main(String[] args) { Zi z = new Zi(); //建立子類對象 z.show(); //調用子類中的show方法 } } b:當子父類中出現了同名成員變量 class Fu{ //Fu中的成員變量。 int num = 5; } class Zi extends Fu{ //Zi中的成員變量 int num = 6; void show(){ //子類的局部變量 int num=7 //直接訪問,遵循就近查找原則 System.out.println(num);//7 //子父類中出現了同名的成員變量時 //在子類中須要訪問父類中非私有成員變量時,須要使用super關鍵字 //訪問父類中的num System.out.println("Fu num="+super.num);//5 //訪問子類中的num2 System.out.println("Zi num2="+this.num);//6 } } class Demo5 { public static void main(String[] args) { Zi z = new Zi(); //建立子類對象 z.show(); //調用子類中的show方法 } }
A:繼承後子類父類成員方法的特性 a:子類的對象調用方法的時候,子類本身有,使用子類,子類本身沒有調用的父類 class Fu{ public void show(){ System.out.println("Fu類中的show方法執行"); } } class Zi extends Fu{ public void show2(){ System.out.println("Zi類中的show2方法執行"); } } public class Test{ public static void main(String[] args) { Zi z = new Zi(); z.show(); //子類中沒有show方法,可是能夠找到父類方法去執行 z.show2(); } } b:爲何要有重寫? class Fu{ public void method(){ //上千行代碼 //Fu類中的方法最早存在,那麼若是項目需求變了,該方法 //功能不可以知足咱們的需求,此時咱們也不會去改這個方法 //由於項目中可能有大量的功能已經使用到該方法,若是隨意修改可能使調用該方法的功能出現問題 //因此使用重寫方式基於原有功能提供更強的功能 } } class Zi extends Fu{ } c:子類中出現與父類如出一轍的方法時,會出現覆蓋操做,也稱爲override重寫、複寫或者覆蓋 class Fu{ public void show(){ System.out.println("Fu show"); } } class Zi extends Fu{ //子類複寫了父類的show方法 public void show(){ System.out.println("Zi show"); } } public class Test{ public static void main(String[] args) { Zi z = new Zi(); z.show(); //Zi show 子類有直接使用子類 } }
A:方法覆蓋的需求 a:案例:好比手機,當描述一個手機時,它具備發短信,打電話,顯示來電號碼功能, 後期因爲手機須要在來電顯示功能中增長顯示姓名和頭像, 這時能夠從新定義一個類描述智能手機,並繼承原有描述手機的類。 並在新定義的類中覆蓋來電顯示功能,在其中增長顯示姓名和頭像功能 b:分析:咱們不改裝(破壞)原來的手機,而是再買一個新的智能手機,不但有原有的功能,並且還有特有功能 例:廠商發佈新手機都是基於原有手機的升級,不會拿着原有的手機在賣,新產一款 1:分析類的構建: 手機類 屬性(成員變量):無 行爲(成員方法): 發短信 打電話 來電顯示:顯示來電號碼 智能手機類: 屬性(成員變量):無 行爲(成員方法): 發短信 打電話 來電顯示:顯示來電號碼,顯示姓名和頭像 手機類和智能手機類有共性內容: 發短信 打電話 顯示來電號碼 2:繼承關係分析: 對於發短信和打電話功能,讓智能手機直接沿用(繼承)手機的就能夠 可是在智能手機中的來電顯示不但實現號碼,還顯示姓名和頭像,一樣的都是來 電顯示功能,智能手機的來電顯示比手機的功能更增強大,咱們考慮使用重寫
//手機類 class Phone{ public void sendMessage(){ System.out.println("發短信"); } public void call(){ System.out.println("打電話"); } public void showNum(){ System.out.println("來電顯示號碼"); } } //智能手機類 class NewPhone extends Phone{ //覆蓋父類的來電顯示號碼功能,並增長本身的顯示姓名和圖片功能 //從現實生活角度考慮沿用原有的showNum方法名便於用戶更快熟悉和接受,而不是再起個新的名字 //用戶還須要花費大量時間慢慢接受 public void showNum(){ //調用父類已經存在的功能使用super //若是不加super這是調用子類自身的showNum(),本身調用本身,遞歸 //方法不斷入棧致使內存溢出 super.showNum(); //增長本身特有顯示姓名和圖片功能 System.out.println("顯示來電姓名"); System.out.println("顯示頭像"); } } public class Test { public static void main(String[] args) { new NewPhone().showNum();//來電顯示 顯示來電姓名 顯示頭像 } }
A:方法覆蓋的注意事項 a:權限:子類方法覆蓋父類方法,必需要保證權限大於等於父類權限。 四大權限:public>默認=protected>private class Fu{ void show(){ } public void method(){ } } class Zi() extends Fu{ public void show(){//編譯運行沒問題 } void method(){//編譯錯誤 } } b:方法定義:子類方法和要重寫的父類的方法:方法的方法名和參數列表都要同樣。 關於方法的返回值: 若是是基本數據類型,子類的方法和重寫的父類的方法返回值類型必須相同 若是是引用數據類型,子類的方法和重寫的父類的方法返回值類型能夠相同或者子類方法的返回值類型是父類方法返回值類型的子類 class Fu{ int show(){ } public Fu method(){ } public Fu method2(){ } } class Zi() extends Fu{ public int show(){//返回值爲基本類型的重寫 } public Fu method(){//子類的方法和重寫的父類的方法返回值類型能夠相同 } public Zi method2(){//子類方法的返回值類型是父類方法返回值類型的子類 } } c:重載與重寫對比: 重載: 權限修飾符(public private 默認):無關 方法名:重載的兩個方法的方法名必須相同 形參列表: 形參類型的順序不一樣 形參的個數不一樣 形參的類型不一樣 三者至少知足一個 返回值類型: 重載與返回值類型無關 重寫: 權限修飾符(public private 默認): 子類方法的權限>=父類的方法的權限 方法名: 子類方法和父類方法必須相同 形參列表: 子類方法和父類方法的形參列表必須相同 返回值類型: 基本類數據類型: 必須相同 引用數據類型: 子類方法的返回值類型和父類方法的返回值類型相同 或者 子類方法的返回值類型是父類方法的返回值類型的 子類
A:抽象類的產生 a:分析事物時,發現了共性內容,就出現向上抽取。會有這樣一種特殊狀況,就是方法 功能聲明相同,但方法功能主體不一樣。那麼這時也能夠抽取,但只抽取方法聲明,不抽 取方法主體。那麼此方法就是一個抽象方法。
A:抽象方法定義的格式: a:public abstract 返回值類型 方法名(參數); 抽象類定義的格式: abstract class 類名 { } b:抽象類示例代碼: /* * 定義類開發工程師類 * EE開發工程師 : 工做 * Android開發工程師 : 工做 * * 根據共性進行抽取,而後造成一個父類Develop * 定義方法,工做: 怎麼工做,具體幹什麼呀 * * 抽象類,不能實例化對象, 不能new的 * 不能建立對象的緣由: 若是真的讓你new了, 對象.調用抽象方法,抽象方法沒有主體,根本就不能運行 * 抽象類使用: 定義類繼承抽象類,將抽象方法進行重寫,建立子類的對象 */ public abstract class Develop { //定義方法工做方法,可是怎麼工做,說不清楚了,講不明白 //就不說, 方法沒有主體的方法,必須使用關鍵字abstract修飾 //抽象的方法,必須存在於抽象的類中,類也必須用abstract修飾 public abstract void work(); }
A:抽象類的使用方式 /* * 定義類,JavaEE的開發人員 * 繼承抽象類Develop,重寫抽象的方法 */ public class JavaEE extends Develop{ //重寫父類的抽象方法 //去掉abstract修飾符,加上方法主體 public void work(){ System.out.println("JavaEE工程師在開發B/S 軟件"); } } /* * 定義Android類,繼承開發人員類 * 重寫抽象方法 */ public class Android extends Develop{ public void work(){ System.out.println("Android工程師開發手機軟件"); } } /* * 測試抽象類 * 建立他的子類的對象,使用子類的對象調用方法 */ public class Test { public static void main(String[] args) { JavaEE ee = new JavaEE(); ee.work();//"JavaEE工程師在開發B/S 軟件" Android and = new Android(); and.work();//"Android工程師開發手機軟件" } }
A:抽象類的特色 a:抽象類和抽象方法都須要被abstract修飾。抽象方法必定要定義在抽象類中。 b:抽象類不能夠直接建立對象,緣由:調用抽象方法沒有意義。 c:只有覆蓋了抽象類中全部的抽象方法後,其子類才能夠建立對象。不然該子類仍是一個抽象類。 之因此繼承抽象類,更多的是在思想,是面對共性類型操做會更簡單。 abstract class A{ public abstract void func(); public abstract void func2(); } class A2 extends A{//A2把A中的兩個抽象方法都重寫掉了 //A2類再也不是抽象類 public void func(){} public void func2(){} } abstract class A3 extends A{//含有抽象方法的類必定是抽象類 public void func(){ } //public abstract void func2();//func2至關於被繼承下來 }
A:抽象類的設計思想 a:抽象類的做用:繼承的體系抽象類,強制子類重寫抽象的方法 抽象員工: 規定一個方法,work工做 EE員工,Android員工 Develop類 抽象類 abstract work(); | ------------- | | EE Android //是我開發的一員必須工做 work(){} work(){}
A:抽象類的細節 a:抽象類必定是個父類? 是的,由於不斷抽取而來的。 b:抽象類中是否能夠不定義抽象方法? 是能夠的,那這個抽象類的存在到底有什麼意義呢?不讓該類建立對象,方法能夠直接讓子類去使用 (適配器設計模式) /* * 抽象類,能夠沒有抽象方法,能夠定義帶有方法體的方法 * 讓子類繼承後,能夠直接使用 */ public abstract class Animal { public void sleep(){ System.out.println("動物睡覺"); } } public class Cat extends Animal{ } public class Test { public static void main(String[] args) { //Cat c = new Cat(); new Cat().sleep();//不讓該類建立對象,方法能夠直接讓子類去使用 } } c:抽象關鍵字abstract不能夠和哪些關鍵字共存? 1:private:私有的方法子類是沒法繼承到的,也不存在覆蓋, 而abstract和private一塊兒使用修飾方法,abstract既要子類去實現這個方法, 而private修飾子類根本沒法獲得父類這個方法。互相矛盾。 /* * 抽象類,能夠沒有抽象方法,能夠定義帶有方法體的方法 * 讓子類繼承後,能夠直接使用 */ public abstract class Animal { // private abstract void show(); //抽象方法,須要子類重寫, 若是父類方法是私有的,子類繼承不了,也就沒有了重寫 } 2:final,暫時不關注,後面學 3:static,暫時不關注,後面學
A:員工案例分析: a:需求描述: 某IT公司有多名員工,按照員工負責的工做不一樣,進行了部門的劃分(研發部員工、維護部員工)。 研發部根據所需研發的內容不一樣,又分爲JavaEE工程師、Android工程師; 維護部根據所需維護的內容不一樣,又分爲網絡維護工程師、硬件維護工程師。 公司的每名員工都有他們本身的員工編號、姓名,並要作它們所負責的工做。 工做內容 JavaEE工程師:員工號爲xxx的 xxx員工,正在研發淘寶網站 Android工程師:員工號爲xxx的 xxx員工,正在研發淘寶手機客戶端軟件 網絡維護工程師:員工號爲xxx的 xxx員工,正在檢查網絡是否暢通 硬件維護工程師:員工號爲xxx的 xxx員工,正在修復打印機 b:繼承體系: 員工 | -------------------------------------------- | | 研發部員工 維護部員工 | | ------------- ----------- | | | | JavaEE工程師 Android工程師 網絡維護工程師 硬件維護工程師 c:詳細描述: 根據員工信息的描述,肯定每一個員工都有員工編號、姓名、要進行工做。 則,把這些共同的屬性與功能抽取到父類中(員工類), 關於工做的內容由具體的工程師來進行指定。 工做內容 JavaEE工程師:員工號爲xxx的 xxx員工,正在研發淘寶網站 Android工程師:員工號爲xxx的 xxx員工,正在研發淘寶手機客戶端軟件 網絡維護工程師:員工號爲xxx的 xxx員工,正在檢查網絡是否暢通 硬件維護工程師:員工號爲xxx的 xxx員工,正在修復打印機 建立JavaEE工程師對象,完成工做方法的調用
A:員工案例Employee類的編寫:按照分析的繼承體系來逐個實現 /* * 定義員工類 * 內容,都是全部子類的共性抽取 * 屬性: 姓名,工號 * 方法: 工做 */ public abstract class Employee { private String id;// 員工編號 private String name; // 員工姓名 public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } //工做方法(抽象方法) public abstract void work(); }
B:員工案例的子類的編寫: /* * 定義研發員工類 * 屬於員工中的一種, 繼承員工類 * 抽象類Develop 給本身的員工定義本身有的屬性 */ public abstract class Develop extends Employee{ } /* * 描述JavaEE開發工程師類 * 工號,姓名 工做方法 * 其餘的員工,也具有這些共性,抽取到父類中,本身就不須要定義了 * 是研發部員工的一種,繼承研發部類 */ public class JavaEE extends Develop{ //重寫他父類的父類的抽象方法 public void work(){ //調用父類的get方法,獲取name,id值 System.out.println("JavaEE的工程師開發淘寶"+ super.getName()+".."+super.getId()); } } /* *定義Android工程師 繼承 研發部員工類,重寫工做方法 */ public class Android extends Developer { @Override public void work() { System.out.println("員工號爲 " + getId() + " 的 " + getName() + " 員工,正在研發淘寶手機客戶端軟件"); } } /* * 定義維護員工類,屬於員工中的一種 * 繼承員工類 * 抽象類Maintainer 給本身的員工定義本身有的屬性 */ public abstract class Maintainer extends Employee{ } /* * 描述的是網絡維護工程師 * 屬於維護部的員工,繼承維護部類 */ public class Network extends Maintainer{ public void work(){ System.out.println("網絡工程師在檢查網絡是否暢通"+super.getName()+"..."+super.getId()); } } /* *定義Hardware硬件維護工程師 繼承 維護部員工類,重寫工做方法 */ public class Hardware extends Maintainer { @Override public void work() { System.out.println("員工號爲 " + getId() + " 的 " + getName() + " 員工,正在修復打印機"); } }
一、根據需求,完成以下代碼(只用繼承,不用抽象類,按照標準格式寫),並在測試類中進行測試。程序員
需求一: 項目經理類 屬性:姓名 工號 工資 獎金 行爲:工做work(打印姓名、工號、工資、獎金) 程序員類 屬性:姓名 工號 工資 行爲:工做work(打印姓名、工號、工資) 需求二: 已知學生類和老師類以下: 屬性:姓名,年齡 行爲:吃飯 老師有特有的方法:講課 學生有特有的方法:學習 需求三: 已知貓類和狗類: 屬性:毛的顏色,腿的個數 行爲:吃飯 貓特有行爲:抓老鼠catchMouse 狗特有行爲:看家lookHome
二、根據需求,完成以下代碼(使用抽象類、按照標準格式寫),並在測試類中進行測試。設計模式
需求一: 具體事物:基礎班老師,就業班老師 共性:姓名,年齡,講課。 特性: 基礎班老師講JavaSE 就業班老師講Android 需求二: 具體事物:基礎班學生,就業班學生 共性:姓名,年齡,學習 特性: 基礎班學生學JavaSE 就業班學生學Android 需求三: 已知貓類和狗類: 屬性:毛的顏色,腿的個數 行爲:吃飯 貓特有行爲:抓老鼠catchMouse 狗特有行爲:看家lookHome