今日內(nèi)容介紹
1、繼承
2吐根、抽象類
3正歼、綜合案例---員工類系列定義
01繼承的概述
*A:繼承的概念
*a:繼承描述的是事物之間的所屬關系,通過繼承可以使多種事物之間形成一種關系體系
*b:在Java中拷橘,類的繼承是指在一個現(xiàn)有類的基礎上去構(gòu)建一個新的類局义,
構(gòu)建出來的新類被稱作子類,現(xiàn)有類被稱作父類
*B:繼承關系的子類特點
*a:子類會自動擁有父類所有非private修飾的屬性和方法
02繼承的定義格式和使用
*A:繼承的格式
class 子類 extends 父類 {}
*B:雇員(Employee)與研發(fā)部員工(Developer)案例:
*cn.itcast.demo01包下:
*Employee.java:
/*
* 定義員工類Employee
*/
class Employee {
String name; // 定義name屬性
public void work() {// 定義員工的工作方法
System.out.println("盡心盡力地工作");
}
}
*Developer.java:
/*
* 定義研發(fā)部員工類Developer 繼承 員工類Employee
* 繼承了父類中所有非private修飾的成員變量
*/
class Developer extends Employee {
// 定義一個打印name的方法
public void printName() {
System.out.println("name=" + name);
}
}
*測試員工類與研發(fā)部員工類:
/*
* 定義測試類
*/
public class Example01 {
public static void main(String[] args) {
Developer d = new Developer(); // 創(chuàng)建一個研發(fā)部員工類對象
d.name = "小明"; // 為該員工類的name屬性進行賦值
d.printName(); // 調(diào)用該員工的printName()方法
d.work(); // 調(diào)用Developer類繼承來的work()方法
}
}
*通過子類對象既可以調(diào)用自身的非private修飾的成員,也可以調(diào)用父類的非private修飾的成員
03繼承的好處
*A:繼承的好處:
*1冗疮、繼承的出現(xiàn)提高了代碼的復用性萄唇,提高軟件開發(fā)效率。
*2术幔、繼承的出現(xiàn)讓類與類之間產(chǎn)生了關系穷绵,提供了多態(tài)的前提。
04繼承的注意事項
*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);//到底是調(diào)用A的還是B的成員變量??無法確定
c.method();//到底是調(diào)用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類的父類。
05繼承的體系.avi 11:00
*A:繼承的體系:
動物(吃)
|
-------------------------
| |
貓科動物(吃,胎生) 爬行動物(吃,卵生)
| |
------------------------------- -----------------
| | | |
貓(吃,抓老鼠,胎生) 虎(吃,領地,胎生) 蛇(吃,冬眠,卵生) 鱷魚(吃,潛水,卵生)
*a:動物體系是對每個具體事物共性的抽取,子類的共性抽取形成父類
*b:父類:具有所有子類的共性內(nèi)容
子類:不但有共性還有自身特有的內(nèi)容
*c:整個繼承體系,越向上越抽象,越向下越具體
06繼承后子類父類成員變量的特點
A:繼承后子類父類成員變量的特點
a:子類的對象調(diào)用成員變量的時候,子類自己有,使用子類,子類自己沒有調(diào)用的父類
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(); //創(chuàng)建子類對象
z.show(); //調(diào)用子類中的show方法
}
}
b:當子父類中出現(xiàn)了同名成員變量
class Fu{
//Fu中的成員變量裹芝。
int num = 5;
}
class Zi extends Fu{
//Zi中的成員變量
int num = 6;
void show(){
//子類的局部變量
int num=7
//直接訪問,遵循就近查找原則
System.out.println(num);//7
//子父類中出現(xiàn)了同名的成員變量時
//在子類中需要訪問父類中非私有成員變量時,需要使用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(); //創(chuàng)建子類對象
z.show(); //調(diào)用子類中的show方法
}
}
07繼承后子類父類成員方法的特性_子類重寫父類方法
A:繼承后子類父類成員方法的特性
a:子類的對象調(diào)用方法的時候,子類自己有,使用子類,子類自己沒有調(diào)用的父類
class Fu{
public void show(){
System.out.println("Fu類中的show方法執(zhí)行");
}
}
class Zi extends Fu{
public void show2(){
System.out.println("Zi類中的show2方法執(zhí)行");
}
}
public class Test{
public static void main(String[] args) {
Zi z = new Zi();
z.show(); //子類中沒有show方法好爬,但是可以找到父類方法去執(zhí)行
z.show2();
}
}
b:為什么要有重寫?
class Fu{
public void method(){
//上千行代碼
//Fu類中的方法最先存在,那么如果項目需求變了,該方法
//功能不能夠滿足我們的需求,此時我們也不會去改這個方法
//因為項目中可能有大量的功能已經(jīng)使用到該方法,如果隨意修改可能使調(diào)用該方法的功能出現(xiàn)問題
//所以使用重寫方式基于原有功能提供更強的功能
}
}
class Zi extends Fu{
}
c:子類中出現(xiàn)與父類一模一樣的方法時局雄,會出現(xiàn)覆蓋操作,也稱為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 子類有直接使用子類
}
}
08方法覆蓋的需求
A:方法覆蓋的需求
a:案例:比如手機炬搭,當描述一個手機時,它具有發(fā)短信穆桂,打電話宫盔,顯示來電號碼功能,
后期由于手機需要在來電顯示功能中增加顯示姓名和頭像享完,
這時可以重新定義一個類描述智能手機灼芭,并繼承原有描述手機的類。
并在新定義的類中覆蓋來電顯示功能般又,在其中增加顯示姓名和頭像功能
b:分析:我們不改裝(破壞)原來的手機,而是再買一個新的智能手機,不但有原有的功能,而且還有特有功能
例:廠商發(fā)布新手機都是基于原有手機的升級,不會拿著原有的手機在賣,新產(chǎn)一款
1:分析類的構(gòu)建:
手機類
屬性(成員變量):無
行為(成員方法):
發(fā)短信
打電話
來電顯示:顯示來電號碼
智能手機類:
屬性(成員變量):無
行為(成員方法):
發(fā)短信
打電話
來電顯示:顯示來電號碼,顯示姓名和頭像
手機類和智能手機類有共性內(nèi)容:
發(fā)短信
打電話
顯示來電號碼
2:繼承關系分析:
對于發(fā)短信和打電話功能,讓智能手機直接沿用(繼承)手機的就可以
但是在智能手機中的來電顯示不但實現(xiàn)號碼,還顯示姓名和頭像,同樣的都是來電顯示功能,智能手機的來電顯示比手機的功能更加強大,我們考慮使用重寫
09方法覆蓋的手機案例實現(xiàn)
//手機類
class Phone{
public void sendMessage(){
System.out.println("發(fā)短信");
}
public void call(){
System.out.println("打電話");
}
public void showNum(){
System.out.println("來電顯示號碼");
}
}
//智能手機類
class NewPhone extends Phone{
//覆蓋父類的來電顯示號碼功能彼绷,并增加自己的顯示姓名和圖片功能
//從現(xiàn)實生活角度考慮沿用原有的showNum方法名便于用戶更快熟悉和接受,而不是再起個新的名字
//用戶還需要花費大量時間慢慢接受
public void showNum(){
//調(diào)用父類已經(jīng)存在的功能使用super
//如果不加super這是調(diào)用子類自身的showNum(),自己調(diào)用自己,遞歸
//方法不斷入棧導致內(nèi)存溢出
super.showNum();
//增加自己特有顯示姓名和圖片功能
System.out.println("顯示來電姓名");
System.out.println("顯示頭像");
}
}
public class Test {
public static void main(String[] args) {
new NewPhone().showNum();//來電顯示 顯示來電姓名 顯示頭像
}
}
10方法覆蓋的注意事項
A:方法覆蓋的注意事項
a:權(quán)限:子類方法覆蓋父類方法,必須要保證權(quán)限大于等于父類權(quán)限茴迁。
四大權(quán)限:public>默認=protected>private
class Fu{
void show(){
}
public void method(){
}
}
class Zi() extends Fu{
public void show(){//編譯運行沒問題
}
void method(){//編譯錯誤
}
}
b:方法定義:子類方法和要重寫的父類的方法:方法的方法名和參數(shù)列表都要一樣寄悯。
關于方法的返回值:
如果是基本數(shù)據(jù)類型,子類的方法和重寫的父類的方法返回值類型必須相同
如果是引用數(shù)據(jù)類型,子類的方法和重寫的父類的方法返回值類型可以相同或者子類方法的返回值類型是父類方法返回值類型的子類
class Fu{
int show(){
}
public Fu method(){
}
public Fu method2(){
}
}
class Zi() extends Fu{
public int show(){//返回值為基本類型的重寫
}
public Fu method(){//子類的方法和重寫的父類的方法返回值類型可以相同
}
public Zi method2(){//子類方法的返回值類型是父類方法返回值類型的子類
}
}
c:重載與重寫對比:
重載:
權(quán)限修飾符(public private 默認):無關
方法名:重載的兩個方法的方法名必須相同
形參列表:
形參類型的順序不同
形參的個數(shù)不同
形參的類型不同
三者至少滿足一個
返回值類型:
重載與返回值類型無關
重寫:
權(quán)限修飾符(public private 默認):
子類方法的權(quán)限>=父類的方法的權(quán)限
方法名:
子類方法和父類方法必須相同
形參列表:
子類方法和父類方法的形參列表必須相同
返回值類型:
基本類數(shù)據(jù)類型:
必須相同
引用數(shù)據(jù)類型:
子類方法的返回值類型和父類方法的返回值類型相同
或者
子類方法的返回值類型是父類方法的返回值類型的 子類
11抽象類的產(chǎn)生
A:抽象類的產(chǎn)生
a:分析事物時,發(fā)現(xiàn)了共性內(nèi)容堕义,就出現(xiàn)向上抽取猜旬。會有這樣一種特殊情況,就是方法功能聲明相同倦卖,但方法功能主體不同洒擦。那么這時也可以抽取,但只抽取方法聲明怕膛,不抽取方法主體熟嫩。那么此方法就是一個抽象方法。
12抽象類的定義格式
A:抽象方法定義的格式:
a:public abstract 返回值類型 方法名(參數(shù));
抽象類定義的格式:
abstract class 類名 {
}
b:抽象類示例代碼:
/*
* 定義類開發(fā)工程師類
* EE開發(fā)工程師 : 工作
* Android開發(fā)工程師 : 工作
*
* 根據(jù)共性進行抽取,然后形成一個父類Develop
* 定義方法,工作: 怎么工作,具體干什么呀
*
* 抽象類,不能實例化對象, 不能new的
* 不能創(chuàng)建對象的原因: 如果真的讓你new了, 對象.調(diào)用抽象方法,抽象方法沒有主體,根本就不能運行
* 抽象類使用: 定義類繼承抽象類,將抽象方法進行重寫,創(chuàng)建子類的對象
*/
public abstract class Develop {
//定義方法工作方法,但是怎么工作,說不清楚了,講不明白
//就不說, 方法沒有主體的方法,必須使用關鍵字abstract修飾
//抽象的方法,必須存在于抽象的類中,類也必須用abstract修飾
public abstract void work();
}
13抽象類的使用方式
A:抽象類的使用方式
/*
* 定義類,JavaEE的開發(fā)人員
* 繼承抽象類Develop,重寫抽象的方法
*/
public class JavaEE extends Develop{
//重寫父類的抽象方法
//去掉abstract修飾符,加上方法主體
public void work(){
System.out.println("JavaEE工程師在開發(fā)B/S 軟件");
}
}
/*
* 定義Android類,繼承開發(fā)人員類
* 重寫抽象方法
*/
public class Android extends Develop{
public void work(){
System.out.println("Android工程師開發(fā)手機軟件");
}
}
/*
* 測試抽象類
* 創(chuàng)建他的子類的對象,使用子類的對象調(diào)用方法
*/
public class Test {
public static void main(String[] args) {
JavaEE ee = new JavaEE();
ee.work();//"JavaEE工程師在開發(fā)B/S 軟件"
Android and = new Android();
and.work();//"Android工程師開發(fā)手機軟件"
}
}
14抽象類特點
A:抽象類的特點
a:抽象類和抽象方法都需要被abstract修飾褐捻。抽象方法一定要定義在抽象類中邦危。
b:抽象類不可以直接創(chuàng)建對象洋侨,原因:調(diào)用抽象方法沒有意義。
c:只有覆蓋了抽象類中所有的抽象方法后倦蚪,其子類才可以創(chuàng)建對象希坚。否則該子類還是一個抽象類。
之所以繼承抽象類陵且,更多的是在思想裁僧,是面對共性類型操作會更簡單。
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相當于被繼承下來
}
15抽象類的設計思想 4:40
A:抽象類的設計思想
a:抽象類的作用:繼承的體系抽象類,強制子類重寫抽象的方法
抽象員工:
規(guī)定一個方法,work工作
EE員工,Android員工
Develop類 抽象類
abstract work();
|
-------------
| |
EE Android //是我開發(fā)的一員必須工作
work(){} work(){}
16抽象類的細節(jié)
A:抽象類的細節(jié)
a:抽象類一定是個父類慕购?
是的聊疲,因為不斷抽取而來的。
b:抽象類中是否可以不定義抽象方法?
是可以的沪悲,那這個抽象類的存在到底有什么意義呢获洲?不讓該類創(chuàng)建對象,方法可以直接讓子類去使用
(適配器設計模式)
/*
* 抽象類,可以沒有抽象方法,可以定義帶有方法體的方法
* 讓子類繼承后,可以直接使用
*/
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();//不讓該類創(chuàng)建對象,方法可以直接讓子類去使用
}
}
c:抽象關鍵字abstract不可以和哪些關鍵字共存?
? 1:private:私有的方法子類是無法繼承到的殿如,也不存在覆蓋贡珊,
而abstract和private一起使用修飾方法,abstract既要子類去實現(xiàn)這個方法,
而private修飾子類根本無法得到父類這個方法涉馁∶挪恚互相矛盾。
/*
* 抽象類,可以沒有抽象方法,可以定義帶有方法體的方法
* 讓子類繼承后,可以直接使用
*/
public abstract class Animal {
// private abstract void show();
//抽象方法,需要子類重寫, 如果父類方法是私有的,子類繼承不了,也就沒有了重寫
}
?
2:final烤送,暫時不關注寒随,后面學
? 3:static,暫時不關注帮坚,后面學
17員工案例分析
A:員工案例分析:
a:需求描述:
某IT公司有多名員工妻往,按照員工負責的工作不同,進行了部門的劃分(研發(fā)部員工试和、維護部員工)讯泣。
研發(fā)部根據(jù)所需研發(fā)的內(nèi)容不同,又分為JavaEE工程師灰署、Android工程師;
維護部根據(jù)所需維護的內(nèi)容不同局嘁,又分為網(wǎng)絡維護工程師溉箕、硬件維護工程師。
公司的每名員工都有他們自己的員工編號悦昵、姓名肴茄,并要做它們所負責的工作。
? 工作內(nèi)容
? JavaEE工程師:員工號為xxx的 xxx員工但指,正在研發(fā)淘寶網(wǎng)站
? Android工程師:員工號為xxx的 xxx員工寡痰,正在研發(fā)淘寶手機客戶端軟件
? 網(wǎng)絡維護工程師:員工號為xxx的 xxx員工抗楔,正在檢查網(wǎng)絡是否暢通
? 硬件維護工程師:員工號為xxx的 xxx員工,正在修復打印機
b:繼承體系:
員工
|
--------------------------------------------
| |
研發(fā)部員工 維護部員工
| |
| | | |
JavaEE工程師 Android工程師 網(wǎng)絡維護工程師 硬件維護工程師
c:詳細描述:
? 根據(jù)員工信息的描述拦坠,確定每個員工都有員工編號连躏、姓名、要進行工作贞滨。
則入热,把這些共同的屬性與功能抽取到父類中(員工類),
關于工作的內(nèi)容由具體的工程師來進行指定晓铆。
? 工作內(nèi)容
? JavaEE工程師:員工號為xxx的 xxx員工勺良,正在研發(fā)淘寶網(wǎng)站
? Android工程師:員工號為xxx的 xxx員工,正在研發(fā)淘寶手機客戶端軟件
? 網(wǎng)絡維護工程師:員工號為xxx的 xxx員工骄噪,正在檢查網(wǎng)絡是否暢通
? 硬件維護工程師:員工號為xxx的 xxx員工尚困,正在修復打印機
? 創(chuàng)建JavaEE工程師對象,完成工作方法的調(diào)用
18員工案例Employee類的編寫
A:員工案例Employee類的編寫:按照分析的繼承體系來逐個實現(xiàn)
/*
* 定義員工類
* 內(nèi)容,都是所有子類的共性抽取
* 屬性: 姓名,工號
* 方法: 工作
*/
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();
}
19員工案例的子類的編寫
B:員工案例的子類的編寫:
/*
* 定義研發(fā)員工類
* 屬于員工中的一種, 繼承員工類
* 抽象類Develop 給自己的員工定義自己有的屬性
*/
public abstract class Develop extends Employee{
}
/*
* 描述JavaEE開發(fā)工程師類
* 工號,姓名 工作方法
* 其他的員工,也具備這些共性,抽取到父類中,自己就不需要定義了
* 是研發(fā)部員工的一種,繼承研發(fā)部類
*/
public class JavaEE extends Develop{
//重寫他父類的父類的抽象方法
public void work(){
//調(diào)用父類的get方法,獲取name,id值
System.out.println("JavaEE的工程師開發(fā)淘寶"+ super.getName()+".."+super.getId());
}
}
/*
*定義Android工程師 繼承 研發(fā)部員工類链蕊,重寫工作方法
*/
public class Android extends Developer {
@Override
public void work() {
System.out.println("員工號為 " + getId() + " 的 " + getName() + " 員工事甜,正在研發(fā)淘寶手機客戶端軟件");
}
}
/*
* 定義維護員工類,屬于員工中的一種
* 繼承員工類
* 抽象類Maintainer 給自己的員工定義自己有的屬性
*/
public abstract class Maintainer extends Employee{
}
/*
* 描述的是網(wǎng)絡維護工程師
* 屬于維護部的員工,繼承維護部類
*/
public class Network extends Maintainer{
public void work(){
System.out.println("網(wǎng)絡工程師在檢查網(wǎng)絡是否暢通"+super.getName()+"..."+super.getId());
}
}
?
/*
*定義Hardware硬件維護工程師 繼承 維護部員工類,重寫工作方法
*/
public class Hardware extends Maintainer {
@Override
public void work() {
System.out.println("員工號為 " + getId() + " 的 " + getName() + " 員工示弓,正在修復打印機");
}
}
20總結(jié)
- 把今天的知識點總結(jié)一遍讳侨。
1、根據(jù)需求奏属,完成如下代碼(只用繼承跨跨,不用抽象類,按照標準格式寫)囱皿,并在測試類中進行測試勇婴。
需求一:
項目經(jīng)理類
屬性:姓名 工號 工資 獎金
行為:工作work(打印姓名、工號嘱腥、工資耕渴、獎金)
程序員類
屬性:姓名 工號 工資
行為:工作work(打印姓名、工號齿兔、工資)
需求二:
已知學生類和老師類如下:
屬性:姓名,年齡
行為:吃飯
老師有特有的方法:講課
學生有特有的方法:學習
需求三:
已知貓類和狗類:
屬性:毛的顏色,腿的個數(shù)
行為:吃飯
貓?zhí)赜行袨?抓老鼠catchMouse
狗特有行為:看家lookHome
2橱脸、根據(jù)需求,完成如下代碼(使用抽象類分苇、按照標準格式寫)添诉,并在測試類中進行測試。
需求一:
具體事物:基礎班老師医寿,就業(yè)班老師
共性:姓名栏赴,年齡,講課靖秩。
特性:
基礎班老師講JavaSE
就業(yè)班老師講Android
需求二:
具體事物:基礎班學生,就業(yè)班學生
共性:姓名,年齡,學習
特性:
基礎班學生學JavaSE
就業(yè)班學生學Android
需求三:
已知貓類和狗類:
屬性:毛的顏色,腿的個數(shù)
行為:吃飯
貓?zhí)赜行袨?抓老鼠catchMouse
狗特有行為:看家lookHome