【Java】繼承、抽象、組合

Kal1發表於2020-10-11

類的繼承

類的繼承
一種由已有的類建立新類的機制,是物件導向程式設計的基石之一。通過繼承,可以根據已有類來定義新類,新類擁有已有類的所有功能。
Java只支援類的單繼承,每個子類只能有一個直接父類
父類是所有子類的公共屬性及方法的集合,子類則是父類的特殊化
繼承機制可以提高程式的抽象程度,提高程式碼的可重用性

基類和派生類

  • 基類(base class)
    也稱超類(superclass)是被直接或間接繼承的類

  • 派生類(derived-class)
    也稱子類 (subclass)繼承其他類而得到的類
    繼承所有祖先的狀態和行為
    派生類可以增加變數和方法
    派生類也可以覆蓋(override)繼承的方法

子類物件與父類物件存在“IS A”(或“is a kind of”)的關係

派生類產生的物件從外部來看,它應該包括

  • 與基類相同的介面
  • 可以具有更多的方法和資料成員
    其內包含著一個基類型別的子物件

繼承語法:

class childClass extends parentClass
{ 
	//類體
}

舉個例子,在一個公司中,有普通員工(Employees)及管理人員(Magagers)兩類人員
職員物件(Employees)可能有的屬性資訊包括
員工號(employeeNumber)
姓名(name)
地址(address)
電話號碼(phoneNumber)
管理人員(Managers)除具有普通員工的屬性外,還可能具有下面的屬性
職責(responsibilities)
所管理的職員(listOfEmployees)

//父類Employee
class Employee
{    
    int  employeeNumbe ;
    String  name, address, phoneNumber ;
}
//子類Manager
class  Manager extends Employee 
{
    //子類增加的資料成員
    String responsibilities, listOfEmployees;
}

需要注意的:
子類不能直接訪問從父類中繼承的私有屬性及方法,但可使用公有(及保護)方法進行訪問

public class B { 
   public int a = 10; 
   private int b = 20; 
   protected int c = 30; 
   public int getB()  { return b; } 
} 
public class A extends B { 
   public int d; 
   public void tryVariables() { 
      System.out.println(a);             //允許 
      System.out.println(b);             //不允許
      System.out.println(getB());        //允許 
      System.out.println(c);             //允許 
    } 
}

隱藏和覆蓋

子類對從父類繼承來的屬性變數及方法可以重新定義

屬性的隱藏

class Parent {
    Number aNumber;
}

class Child extends Parent {
    Float aNumber;
}

  • 子類中宣告瞭與父類中相同的成員變數名,則從父類繼承的變數將被隱藏
  • 子類擁有了兩個相同名字的變數,一個繼承自父類,另一個由自己宣告
  • 當子類執行繼承自父類的操作時,處理的是繼承自父類的變數;而當子類執行它自己宣告的方法時,所操作的就是它自己宣告的變數

訪問被隱藏的父類屬性

  • 呼叫從父類繼承的方法,則操作的是從父類繼承的屬性
  • 使用super.屬性
class A1
{   int x = 2;    
    public void setx(int i) 
    {   x = i;    }
    void printa()
    {System.out.println(x);}  
}
class B1 extends A1
{   int x=100;
    void printb() 
    {  super.x = super.x +10 ;
       System.out.println("super.x=" + super.x + "  x= " + x);
    }  
}

public class Exam4_4Test 
{  public static void main(String[] args)
    {   A1 a1 = new A1();  
         a1.setx(4);   
         a1.printa();

         B1 b1 = new B1();     
         b1.printb();     
         b1.printa();  
  
         b1.setx(6);  // 將繼承x值設定為6
         b1.printb();     
         b1.printa();
         a1.printa();
    }  
}

執行結果:
4
super.x= 12 x= 100
12
super.x= 16 x= 100
16
4

操作父類靜態屬性舉例
子類不能繼承父類中的靜態屬性,但可以對父類中的靜態屬性進行操作。如在上面的例子中,將“int x = 2;”改為“static int x = 2;”,再編譯及執行程式,會得到下面的結果
4 super.x= 14 x= 100 14 super.x= 16 x= 100 16 16
在上面的結果中,第一行及最後一行都是語句“a1.printa();”輸出的結果,顯然類B中的printb()方法修改的是類A中的靜態屬性x

方法覆蓋
如果子類不需使用從父類繼承來的方法的功能,則可以宣告自己的同名方法,稱為方法覆蓋
覆蓋方法的返回型別,方法名稱,引數的個數及型別必須和被覆蓋的方法一模一樣

只需在方法名前面使用不同的類名或不同類的物件名即可區分覆蓋方法和被覆蓋方法

覆蓋方法的訪問許可權可以比被覆蓋的寬鬆,但是不能更為嚴格

方法覆蓋的應用場合

  • 子類中實現與父類相同的功能,但採用不同的演算法或公式
  • 在名字相同的方法中,要做比父類更多的事情
  • 在子類中需要取消從父類繼承的方法

注意事項
必須覆蓋的方法
派生類必須覆蓋基類中的抽象的方法,否則派生類自身也成為抽象類.
不能覆蓋的方法
基類中宣告為final的終結方法
基類中宣告為static 的靜態方法
呼叫被覆蓋的方法
super.overriddenMethodName();

Object類

終結類與終結方法

抽象類

泛型

類的組合

包的應用

本章小結

相關文章