繼承


繼承的概念和實現:
繼承須要 is-a 的關係,父類更通用更抽象,子類更特殊更具體。java

繼承背後的思想就是基於已存在的類來構建新類。ide

當從已存在類繼承是,就重用了它的方法和屬性,還能夠添加新的方法和屬性來定製新類以應對需求。
父類擁有的屬性和方法 子類均可以擁有,但子類擁有的屬性和方法父類未必有。
約定:從其餘類導出的類叫子類,被導出的類叫父類。
在Java中,除了 Object 類以外,全部類都是子類,都有惟一的父類。
一個子類只能有一個父類。 //只能有一個親生父親測試

類之間的關係:
is -a 繼承體現
Has -a 組合體現
Like -a 實現接口體現
繼承的意義:
代碼重用、體現不一樣的抽象層次this

父子類關係
父類更抽象、更通常
子類更具體、更特殊編碼

 

 

 

extends 關鍵字:
在java語言中,用 extends 關鍵字來表示一個類繼承了另外一個類spa

 

 

繼承和多態都是面向對象程序設計的特色。使用繼承能夠在一個父類的基礎上再建立一個子類,這個子類不但擁有父類已有的屬性和方法,還能夠建立屬於本身的屬性和方法。因爲子類和父類之間的關係,從而引出了方法重寫和方法重載的問題。方法重寫及方法重載在繼承和多態性方面的應用中會存在不少問題,這些概念很容易混淆,掌握重寫和重載的區別對學會使用多態的方式編寫程序、提升程序的可維護性奠基了基礎。

1、方法重寫(0veriding)
如何定義重寫:在Java程序中,類的繼承關係能夠產生一個子類,子類繼承父類,它具有了父類全部的特徵,繼承了父類全部的方法和變量。子類能夠定義新的特徵,當子類須要修改父類的一些方法進行擴展,增大功能,程序設計者經常把這樣的一種操做方法稱爲重寫,也叫稱爲覆寫或覆蓋。重寫體現了Java優越
性,重寫是創建在繼承關係上,它使語言結構更加豐富。在Java中的繼承中,子類既能夠隱藏和訪問父類的方法,也能夠覆蓋繼承父類的方法。在Java中覆蓋繼承父類的方法就是經過方法的重寫來實現的。

所謂方法的重寫是指子類中的方法與父類中繼承的方法有徹底相同的返回值類型、方法名、參數個數以及參數類型。這樣,就能夠實現對父類方法的覆蓋。例如:下面的代碼實現了方法的重寫。.net


class Person//定義父類
fpublic void print(){//父類中的方法
System.out.println( 父類Person的print方法! );
}
}
class Student extends Person//定義子類繼承Person類
{public void print(){//方法的重寫
System.out.println( 子類Student的print方法! );
}
}
public class 0verrideExampleO1
{public static void main(String args[])
{Student s=new Student();
S.print();
}
}

運行結果:子類Student的print方法!

能夠看出,當子類重寫了父類中的print()方法後,使用S調用的是子類的print()方法,父類中的print()方法被覆蓋了。也就是說,若是如今子類將父類中的方法重寫了,調用的時候確定是調用被重寫過的方法,那麼若是如今必定要調用父類中的方法該怎麼辦呢?此時,經過使用.. super關鍵就能夠實現這個功能,super關鍵字能夠從子類訪問父類中的內容,若是要訪問被重寫過的方法,使用「super.方法名(參數列表)」的形式調用。

例如:
Class Person
{public void print () {
System.out.println( 父類Person的print方法! );
}
}
class Student extends Person
{public void print () {
super.print(://訪問父類中被子類覆寫過的方法
System.out.println(" 子類Student的print方法!" );
}
}
public class OverrideExample02
{public static void main(String args[])
{Student s=new Student();
S.print();
}
}
運行結果:父類Person的print方法!
子類Student的print方法 !
若是要使用super關鍵字不必定非要在方法重寫以後使用,

也能夠明確地表示某個方法是從父類中繼承而來的。使用super設計

只是更加明確的說,要從父類中查找,就不在子類查找了。code

2、重寫規則
在重寫方法時,須要遵循如下的規則: 

(一)  父類方法的參數列表必須徹底與被子類重寫的方法的參數列表相同,不然不能稱其爲重寫而是重載。.. 
(二)  父類的返回類型必須與被子類重寫的方法返回類型相同,不然不能稱其爲重寫而是重載。.. 
(三)  Java中規定,被子類重寫的方法不能擁有比父類方法更加嚴格的訪問權限。訪問權限大小關係爲:

編寫過Java程序的人就知道,父類中的方法並非在任何狀況下均可以重寫的,當父類中方法的訪問權限修飾符爲private時,該方法只能被本身的類訪問,不能被外部的類訪問,在子類是不能被重寫的。若是定義父類的方法爲public,在子類定義爲private,程序運行時就會報錯。例如: 

class Person
{public void print()(//public訪問權限
System.out.println( "父類Person的print方法! ");
}
}
Class Stedent extends Person
{private void print()(//重寫方法下降了訪問權限,錯誤
System.out.println( "子類Student的print方法!" );
}
}
(四)  因爲父類的訪問權限修飾符的限制必定要大於被子類重寫方法的訪問權限修飾符,而private權限最小。因此若是某一個方法在父類中的訪問權限是private,那麼就不能在子類中對其進行重寫。若是從新定義,也只是定義了一個新的方法,不會達到重寫的效果。 

(五)  在繼承過程當中若是父類當中的方法拋出異常,那麼在子類中重寫父類的該方法時,也要拋出異常,並且拋出的異常不能多於父類中拋出的異常(能夠等於父類中拋出的異常)。換句話說,重寫方法必定不能拋出新的檢查異常,或者比被重寫方法聲明更加寬泛的檢查型異常。例如,父類的一個方法申明瞭一個檢查異常IOException,在重寫這個方法時就不能拋出Exception,只能拋出IOException的子類異常,能夠拋出非檢查異常。htm


一樣的道理,若是子類中建立了一個成員變量,而該變量和
父類中的一個變量名稱相同,稱做變量重寫或屬性覆蓋。可是此
概念通常不多有人去研究它,由於意義不大。

3、方法重載(Overloading)

(一)  如何定義重載。方法的重寫和重載只有一個字不一樣,不少初學者認爲這二者十分類似,其實否則。方法重載是讓類以統一的方式處理不一樣類型數據的一種手段。調用方法時經過傳遞給它們的不一樣個數和類型的參數來決定具體使用哪一個方法,這就是多態性。
所謂方法重載是指在一個類中,多個方法的方法名相同,可是參數列表不一樣。參數列表不一樣指的是參數個數、參數類型或者參數的順序不一樣。方法的重載在實際應用中也會常常用到。不只是通常的方法,構造方法也能夠重載。下面經過一個實例來分析。
重載的定義和使用方法。 

Class Person {
{String name; 
int age;
void print(){ 
System.out.println("姓名:" +name+"年齡:" +age); 
}
void print(String a,int b){ 
System.out.println("姓名:" +a+"年齡:"+b); 
void print(String a,int b,intC){ 
System.out.println("姓名:"+a+"年齡:" +b+"ID號:" +c); 
}
void print(String a,int b,doubleC){ 
System.out.println("姓名:"+a+"年齡:" +b+"ID號:"+c); 

}

public class OverLoadExampleOL 
{publicstaticvoidmain(String args[]) 
{Personpl=newPerson();
p1.nanle="李明";
p1.age=22;
p1.print(); 
p1.print("王小早",19); 
p1.print("金波",18,100325); 
p1.print("婉寧",25,110903); 

}

在上面的程序中,能夠看到Person類中有多個名爲 void print的方法,這就是方法的重載。執行程序,運行結果以下:

姓名:李明年齡:22
姓名:王小早年齡:l9
姓名:金波年齡:18ID號:10 00325
姓名:婉寧年齡:25ID號:110903

在方法重載時,方法之間須要存在必定的聯繫,由於這樣能夠提升程序的可讀性,通常只重載功能類似的方法重載規則。重載是指咱們能夠定義一些名稱相同的方法,經過定義不一樣的參數來區分這些方法,而後再調用時,Java虛擬機就會根
據不一樣的參數列表來選擇合適的方法執行。也就是說,當一個重載方法被調用時,Java用參數的類型和.. (或)個數來決定實際調用的重載方法。所以,每一個重載方法的參數的類型或個數必須是不一樣。雖然每一個重載方法能夠有不一樣的返回類型,
但返回類型並不足以區分所使用的是哪一個方法。當Java調用一個重載方法是,參數與調用參數匹配的方法被執行。在使用重載要注意如下的幾點:

1.在使用重載時只能經過不一樣的參數列表,必須具備不一樣的參數列表。例如,不一樣的參數類型,不一樣的參數個數,不一樣的參數順序。固然,同一方法內的幾個參數類型必須不同,例如能夠是 fun(int,float),可是不能爲 fun(int,int)。
2.不能經過訪問權限、返回類型、拋出的異常進行重載。
3.方法的異常類型和數目不會對重載形成影響。.. 
4.能夠有不一樣的返回類型,只要參數列表不一樣就能夠了。
5.能夠有不一樣的訪問修飾符。

6.能夠拋出不一樣的異常。

4、方法重寫與方法重載的區別
經過上面例子的分析,咱們能夠將方法重寫和重載的區別總
結成這樣一個表格,以下:

區別點

重載

重寫(覆寫)

英文

Overloading

Overiding

定義

方法名稱相同,參數的類型或個數不一樣

方法名稱、參數類型、返回值類型所有相同

對權限沒有要求

被重寫的方法不能擁有更嚴格的權限

範圍

發生在一個類中

發生在繼承類中

 

5、結束語
在面向對象程序設計的思想中,類的繼承和多態性主要就是體如今子類重寫父類的方法。而構造方法的重載做爲方法重載的一個典型特例,能夠經過重載構造方法來表達對象的多種初始化行爲。靈活的運用方法重寫與方法重載,不只能減小編碼的工做量,也能大大提升程序的可維護性及可擴展性。用好重寫和重載
能夠設計一個結構清晰而簡潔的類,能夠說重寫和重載在編寫代碼過程當中的做用非同通常。

參考文獻

 

 

this關鍵字:當前對象的引用

當子父類的成員出現同名時,能夠經過super 來進行區分。
子類的構造方法中,經過super關鍵字調用父類的構造方法 先產生父類的對象
經過調用父類的構造方法,完成對相關屬性值的初始化。

 

 

 

強調:
當構造一個子類對象的時候必定會先調用父類的構造方法來構造父類的對象。調用父類的構造方法的語句必須是子類構造方法中的第一條指令。

 

 

  • 抽象類和抽象方法都經過abstract關鍵字來修飾。
  • 抽象類不能實例化。 抽象類中能夠沒有、能夠有一個或多個抽象方法,甚至能夠所有爲抽象方法。
  • 抽象方法只有方法聲明,沒有方法實現。有抽象方法的類聲明爲抽象類。子類必須重寫全部的抽象方法才能實例化,不然子類仍是一個抽象類。
注意:public void print(){}  不是抽象方法,而是有實現但實現爲空的普通方法。
public abstract void print(); 纔是抽象方法,別忘記了最後的分號。
abstract能夠用來修飾類和方法,但不能用來修飾屬性和構造方法。
 1 package cn.jbit.car;
 2 
 3 /**
 4  * 汽車抽象類。
 5  */
 6 public abstract class MotoVehicle {
 7     private String no;// 汽車牌號
 8     private String brand;// 汽車品牌
 9     /**
10      * 無參構造方法。
11      */
12     public MotoVehicle() {
13     }
14     /**
15      * 有參構造方法。
16      * @param no  汽車牌號
17      * @param brand  汽車品牌
18      */
19     public MotoVehicle(String no, String brand) {
20         this.no = no;
21         this.brand = brand;
22     }
23     public String getNo() {
24         return no;
25     }
26     public String getBrand() {
27         return brand;
28     }
29     /**
30      * 抽象方法,計算汽車租賃價。
31      * */
32     public abstract int calRent(int days);
33 
34 }

 

 

 1 package cn.jbit.car;
 2 
 3 /**
 4  * 轎車類,繼承汽車類。
 5  */
 6 public final class Car extends MotoVehicle {
 7     private String type;// 汽車型號
 8     public Car() {
 9     }
10     public Car(String no, String brand, String type) {
11         super(no, brand);
12         this.type = type;
13     }
14     public String getType() {
15         return type;
16     }
17     public void setType(String type) {
18         this.type = type;
19     }
20     /**
21      * 計算轎車租賃價
22      */
23     public int calRent(int days) {
24         if ("1".equals(type)) {// 表明550i
25             return days * 500;
26         } else if ("2".equals(type)) {// 2表明商務艙GL8
27             return 600 * days;
28         } else {
29             return 300 * days;
30         }
31     }
32 }

 

 

 

 1 package cn.jbit.car;
 2 
 3 /**
 4  * 客車類,繼承汽車類。
 5  */
 6 public final class Bus extends MotoVehicle {
 7     private int seatCount;// 座位數
 8     public Bus() {
 9     }
10     public Bus(String no, String brand, int seatCount) {
11         super(no, brand);
12         this.seatCount = seatCount;
13     }
14     public int getSeatCount() {
15         return seatCount;
16     }
17     public void setSeatCount(int seatCount) {
18         this.seatCount = seatCount;
19     }
20     /**
21      * 計算客車租賃價
22      */
23     public int calRent(int days) {
24         if (seatCount <= 16) {
25             return days * 800;
26         } else {
27             return days * 1500;
28         }
29     }
30 }

 

 

 

 

package cn.jbit.car;

import java.util.Scanner;
/**
 * 測試類。
 */
public class TestRent {
    public static void main(String[] args) {        
        String no,brand,mtype,type;            
        int seatCount,days,rent;
        Car car;
        Bus bus;
        Scanner input = new Scanner(System.in);        
        System.out.println("歡迎您來到汽車租賃公司!");
        System.out.print("請輸入要租賃的天數:");
        days=input.nextInt();    
        System.out.print("請輸入要租賃的汽車類型(1:轎車      二、客車):");
        mtype = input.next();        
        if("1".equals(mtype)){
            System.out.print("請輸入要租賃的汽車品牌(一、寶馬    二、別克):");
            brand=input.next();
            System.out.print("請輸入轎車的型號 ");
            if("1".equals(brand))
                System.out.print("一、550i:");
            else
                System.out.print("二、商務艙GL8  三、林蔭大道");
            type=input.next();
            no="京BK5543";//簡單起見,直接指定汽車牌號
            System.out.println("分配給您的汽車牌號是:"+no);
            car =new Car(no,brand,type);
            rent=car.calRent(days);
        }
        else{
            System.out.print("請輸入要租賃的客車品牌(一、金盃 二、金龍):");
            brand=input.next();
            System.out.print("請輸入客車的座位數:");
            seatCount=input.nextInt();
            no="京AU8769";//簡單起見,直接指定汽車牌號
            System.out.println("分配給您的汽車牌號是:"+no);
            bus=new Bus(no,brand,seatCount);
            rent=bus.calRent(days);
        }        
        System.out.println("\n顧客您好!您須要支付的租賃費用是"+rent+"。");
            

    }
}
相關文章
相關標籤/搜索