1. 程式人生 > >1、繼承 2、抽象類 3、綜合案例---員工類系列定義

1、繼承 2、抽象類 3、綜合案例---員工類系列定義

今日內容介紹
1、繼承
2、抽象類
3、綜合案例---員工類系列定義
 






###01繼承的概述
*A:繼承的概念
    *a:繼承描述的是事物之間的所屬關係,通過繼承可以使多種事物之間形成一種關係體系
        *b:在Java中,類的繼承是指在一個現有類的基礎上去構建一個新的類,
            構建出來的新類被稱作子類,現有類被稱作父類
      *B:繼承關係的子類特點  
        *a:子類會自動擁有父類所有非private修飾的屬性和方法

###02繼承的定義格式和使用
*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修飾的成員


###03繼承的好處
    *A:繼承的好處:
        *1、繼承的出現提高了程式碼的複用性,提高軟體開發效率。
        *2、繼承的出現讓類與類之間產生了關係,提供了多型的前提。


###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);//到底是呼叫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類的父類。






###05繼承的體系.avi 11:00
   *A:繼承的體系:


                  動物(吃)
                    |
           -------------------------
           |                        |
        貓科動物(吃,胎生)      爬行動物(吃,卵生)
           |                            |
-------------------------------        -----------------      
     |                 |        |                |
貓(吃,抓老鼠,胎生)   虎(吃,領地,胎生)  蛇(吃,冬眠,卵生)  鱷魚(吃,潛水,卵生)
    
    
    *a:動物體系是對每個具體事物共性的抽取,子類的共性抽取形成父類
    *b:父類:具有所有子類的共性內容
       子類:不但有共性還有自身特有的內容
    *c:整個繼承體系,越向上越抽象,越向下越具體








###06繼承後子類父類成員變數的特點 
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方法
}
}




###07繼承後子類父類成員方法的特性_子類重寫父類方法 
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 子類有直接使用子類
}
}  
       


###08方法覆蓋的需求 
    A:方法覆蓋的需求 
    a:案例:比如手機,當描述一個手機時,它具有發簡訊,打電話,顯示來電號碼功能,
    後期由於手機需要在來電顯示功能中增加顯示姓名和頭像,
    這時可以重新定義一個類描述智慧手機,並繼承原有描述手機的類。
    並在新定義的類中覆蓋來電顯示功能,在其中增加顯示姓名和頭像功能


    b:分析:我們不改裝(破壞)原來的手機,而是再買一個新的智慧手機,不但有原有的功能,而且還有特有功能
           例:廠商釋出新手機都是基於原有手機的升級,不會拿著原有的手機在賣,新產一款 
          1:分析類的構建:
           手機類
            屬性(成員變數):無
            行為(成員方法):
               發簡訊
               打電話
               來電顯示:顯示來電號碼
          智慧手機類:
            屬性(成員變數):無
            行為(成員方法):
              發簡訊
              打電話
              來電顯示:顯示來電號碼,顯示姓名和頭像
          
          手機類和智慧手機類有共性內容:
              發簡訊
              打電話
              顯示來電號碼
          
          2:繼承關係分析:
            對於發簡訊和打電話功能,讓智慧手機直接沿用(繼承)手機的就可以
            但是在智慧手機中的來電顯示不但實現號碼,還顯示姓名和頭像,同樣的都是來電顯示功能,智慧手機的來電顯示比手機的功能更加強大,我們考慮使用重寫
 
###09方法覆蓋的手機案例實現 
//手機類
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();//來電顯示  顯示來電姓名 顯示頭像
}
}
    
###10方法覆蓋的注意事項 
   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 預設): 
      子類方法的許可權>=父類的方法的許可權
    方法名: 
      子類方法和父類方法必須相同
    形參列表: 
       子類方法和父類方法的形參列表必須相同
    返回值型別:
      基本類資料型別:
        必須相同
      引用資料型別:
       子類方法的返回值型別和父類方法的返回值型別相同
       或者
       子類方法的返回值型別是父類方法的返回值型別的 子類




###11抽象類的產生 
      A:抽象類的產生
        a:分析事物時,發現了共性內容,就出現向上抽取。會有這樣一種特殊情況,就是方法功能宣告相同,但方法功能主體不同。那麼這時也可以抽取,但只抽取方法宣告,不抽取方法主體。那麼此方法就是一個抽象方法。
###12抽象類的定義格式 
A:抽象方法定義的格式:
   a:public abstract 返回值型別 方法名(引數);
     抽象類定義的格式:
abstract class 類名 {

  }
    b:抽象類示例程式碼:
   /*
*  定義類開發工程師類
*    EE開發工程師 :  工作
*    Android開發工程師 : 工作
*    
*    根據共性進行抽取,然後形成一個父類Develop
*    定義方法,工作: 怎麼工作,具體幹什麼呀
*    
*    抽象類,不能例項化物件, 不能new的
*    不能建立物件的原因:  如果真的讓你new了, 物件.呼叫抽象方法,抽象方法沒有主體,根本就不能執行
*    抽象類使用: 定義類繼承抽象類,將抽象方法進行重寫,建立子類的物件
*/
public abstract class Develop {
   //定義方法工作方法,但是怎麼工作,說不清楚了,講不明白
//就不說, 方法沒有主體的方法,必須使用關鍵字abstract修飾
//抽象的方法,必須存在於抽象的類中,類也必須用abstract修飾
public abstract void work();
}








###13抽象類的使用方式
    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工程師開發手機軟體"
}
}
        


###14抽象類特點
  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相當於被繼承下來
      }


###15抽象類的設計思想 4:40
    A:抽象類的設計思想
      a:抽象類的作用:繼承的體系抽象類,強制子類重寫抽象的方法
        抽象員工:
          規定一個方法,work工作
          EE員工,Android員工 
           
           Develop類 抽象類
           abstract work();
               |
        -------------
       |             |
      EE            Android  //是我開發的一員必須工作
      work(){}       work(){}


###16抽象類的細節
   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,暫時不關注,後面學






###17員工案例分析
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工程師物件,完成工作方法的呼叫




###18員工案例Employee類的編寫
   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(); 
}




###19員工案例的子類的編寫
   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() + " 員工,正在修復印表機");
}
}


###20總結
* 把今天的知識點總結一遍。