原來你是這樣的JAVA[03]-繼承、多態、抽象類別,java多態

來源:互聯網
上載者:User

原來你是這樣的JAVA[03]-繼承、多態、抽象類別,java多態
一、繼承


Java中的繼承使用關鍵字extends ,跟C#的文法略有差別。

1.子類構造器


java會自動在子類的構造器中插入對父類構造器的調用,也就是說在子類可以訪問父類之前已經完成了父類的初始化。
如果想調用帶參數的父類構造器,應該使用super關鍵字。

/**  * @author 陳敬  * @date 18/1/17  */public class Product {     private String name;    public Product(String name) {         this.name = name;         System.out.println("[Product constructor]");     }}public class Bread extends Product {     private int price;    public Bread(String name, int price) {         super(name);//調用父類構造器         this.price = price;         System.out.println("[Bread constructor]");     }}

我們建立一個Bread類的執行個體,看看調用順序。

@Testpublic void testConstructor(){     Bread bread=new Bread("毛毛蟲麵包",10);}

列印結果:
[Product constructor]
[Bread constructor]

2.調用父類方法


子類是不能直接存取到父類的私人域的,如果想訪問只能藉助父類公開的get訪問器。子類調用父類中的方法也需要使用super關鍵字。

public class Product {    private String name;    public String getName() {        return name;    }    public Product(String name) {        this.name = name;    }}public class Bread extends Product {    public Bread(String name) {        super(name);    }    public void display(){        System.out.println(getName());    }}

然後寫個單元測試:

   @Test    public void testPrivate(){        Bread bread=new Bread("毛毛蟲麵包");        bread.display();//毛毛蟲麵包    }

需要說明一點,super並不是一個對象的引用,不能將super賦值給變數,它只是一個特殊的關鍵字,告訴編輯器要調用父類中的方法。

3.關於重載


如果父類中存在重載方法,子類又進行了重載,會覆蓋父類中的方法嗎?實際上,父類和子類中的方法都可以正常重載,不會被覆蓋。
首先在父類Product中添加方法getDescription():

public class Product {     ……    public String getDescription() {         return "[Product]name="+name;     }}

然後在子類中重載該方法:

public class Bread extends Product {     ……    public String getDescription(String storeName) {        return "[Bread]storename="+storeName;     }}

增加一個單元測試:

public class ExtendClassTests {     @Test     public void testOverload(){         Bread bread=new Bread("豆沙麵包",9);         System.out.println(bread.getDescription());         System.out.println(bread.getDescription("味多美"));     }}

輸出:
[Product]name=豆沙麵包
[Bread]storename=味多美

4.繼承準則


繼承準則:盡量少用繼承。一般用繼承表達行為間的差異,用組合表示狀態上的變化。

二、多態

 

1.變數多態


在Java中物件變數是多態的,一個Product變數可以引用Product對象,也可以引用一個Product子類的對象。

@Test
public void testParent(){
Product product=new Bread("毛毛蟲麵包",10);
product.display();

//強制類型轉換
if(product instanceof Bread){
Bread brand=(Bread)product;
brand.display("味多美");
}
}

由於Bread執行個體向上轉型為Product類型,所以不能再調用Bread.getDescription(String storeName)方法。
如果需要將父類強制轉換為子類時,要先通過instanceof檢測物件類型,我們最好盡量避免使用強制類型轉換。

2.動態綁定


所謂動態綁定,就是在運行時根據對象的類型決定要調用的方法。在java中,動態綁定是預設行為,不需要添加額外的關鍵字實現多態。

再寫個demo來看一下,在父類和子類中重載了display方法。

public class Product {     private String name;    public Product(String name) {         this.name = name;     }    public void display() {         System.out.println("[Product]getDescription()");     }}public class Bread extends Product {     private int price;    public Bread(String name, int price) {         super(name);         this.price = price;     }    @Override     public void display() {         System.out.println("[Bread]getDescription()");     }     public void display(String storeName) {         System.out.println("[Bread]getDescription(String storeName)");     }}

添加單元測試:

@Testpublic void dynamicBind(){     Product product=new Product("product");     product.display();  //[Product]getDescription()    Bread bread=new Bread("毛毛蟲",9);     bread.display();  //[Bread]getDescription()     bread.display("maimai");  //[Bread]getDescription(String storeName)    Product product1=bread;     product1.display();  //[Bread]getDescription()}

 

虛擬機器為每個類建立一個方法表,列出所有方法的簽名和實際調用的方法。這樣一來,當動態調用方法的時候,只需要尋找方法表就能快速的找到真正調用的方法了。
Product:
     display()->Product.display()
Bread:
     display()->Bread.display()
     display(String name)->Bread.display(String name)
 
完整源碼參見:https://github.com/cathychen00/cathyjava     /_08_extend

三、抽象類別

定義抽象方法用用abstract關鍵字,它僅有聲明而沒有方法體。
包含抽象方法的類叫做抽象類別,如果一個類包含一個或多個抽象方法,那麼必須被定義為抽象類別。
如果一個類從抽象類別繼承,那麼必須為抽象類別中的所有抽象方法提供實現,否則該類也必須被定義為抽象類別。
看一個情境:我們有一些定時任務,要進行的工作流程類似,只有具體一部分細節內容不同。我們可以定義一個抽象基類BaseJob,再不同的部分封裝為抽象方法,具體的實現在子類中進行。

public abstract class BaseJob {     public void run(){         System.out.println("==START "+getDescription()+"==");         String lastJobId=getLastJobId();         execute(lastJobId);         writeLog();         System.out.println("==END "+getDescription()+"==");     }    protected abstract String getDescription();    protected abstract void execute(String jobId);    private void writeLog() {         System.out.println("write log to DB");     }    private String getLastJobId() {         return "job1221";     }}
public class ArticleJob extends BaseJob {     @Override     protected String getDescription() {         return "抓取文章任務";     }    @Override     protected void execute(String jobId) {         System.out.println("抓取網站新聞文章 jobid="+jobId);     }    public static void main(String[] args) {         BaseJob articleJob=new ArticleJob();         articleJob.run();     }}

建立單元測試,調用ArticleJob看看。

@Testpublic void articleJob(){     BaseJob articleJob=new ArticleJob();     articleJob.run();}

運行結果:

==START 抓取文章任務==抓取網站新聞文章 jobid=job1221write log to DB==END 抓取文章任務==

當再次添加符合該流程的定時任務時,只需要建立一個類,實現BaseJob就可以了。

完整例子:https://github.com/cathychen00/cathyjava /09_abstract

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.