抽象類和接口的使用

開篇廢話

入職后一直研究Android framework的東西,大概花了一個月鼓搗了一個系統應用“應用雙開”。雖然也是敲代碼,但是主要是在Android源碼中進行修改,也可以說很久沒用java去寫一個完整的東西了。近來公司有個小工具需要開發,上頭應該覺得功能很簡單,所以讓我一個人開發。具體功能需求不便透露,主要是一個windows應用。本來我打算用C#寫,但是老大說最好用java,最終選了java swing來開發。這是一個很古老的東西,反正我也不熟悉,在大概學習了swing的組件使用之后,就開始動手coding了。

java思想

其實不管java也好,其他面向對象語言也好。面向對象的思想就是分工而治,統一管理。這里我就不吹逼面向對象了,畢竟能力有限,吹逼能力有限,道行尚淺。大家記住這幾個字分工而治,統一管理

例如

說一千道一萬,眼見為實耳聽為虛。我寫的工具中有這么一項需求。大致類似于,我要寫滿漢全席的食譜,總共一百零八道菜,每道菜都需要配圖(UI)和做法(文本),最終寫到一個冊子中(文本匯總)。

需求分析:

1.一百零八道菜,每個菜都不同,應該對應著有108個類吧。
2.每道菜都需要配圖和做法,對應著每個類都應該有一個pic()方法和cook()方法吧。
3.最終寫到一個冊子中。匯總:調用所有類的cook()方法,寫到一個文本中。

代碼設計

一定要記住,不要忙于寫代碼,而是搞清楚功能邏輯,不然寫到一半改需求是真的很要命,我就吃了這個虧,好在我前期代碼結構設計還算可以,不至于重頭來過。

言歸正傳:108道菜,每道菜都不同,如果沒有重樣的菜,就意味應該有108個類。每個類都有pic()和cook()方法,說明這是共用類,匯總的時候去調用每個類的cook()方法。
按照道理講功能的邏輯是這樣沒錯了,如果這108類每個類都不一樣的話,這108類看來是必不可少了,pic()和cook(),屬于類的方法,無可厚非,但是匯總時,我總不能把每個類都實例化一遍然后去調用各自的cook方法吧。所以這時候,java的抽象類和接口就得派上用場了。抽象類和接口都是用于類的繼承,抽象類只能單繼承,接口可以多繼承,這些基礎的概念,想必大家都懂,不懂沒關系,可以上網去查啊http://www.lxweimin.com/p/038f0b356e9a
但是值得去講的是:抽象類和接口中都是抽象方法,就是沒有實現的方法,語法上支持你去調用這個方法,但是最終調用的是繼承了該類或接口并實現了該方法的類。
所以:我們可以這樣做,這些如何靈活運行接口和抽象類就看各自的本事了,我大致講解一下我的做法。

首先我定義了一個抽象類
public abstract class Food {

    public String type = "";

    public Food() {
    }

    abstract public String cook();
    abstract public void pic();
}

其中有兩個未實現的抽象方法,因為考慮到108到菜也分菜系,所以用了type變量用來標識菜系。
現在我們要做兩個菜系的菜,粵菜,和川菜。不管他們是哪個菜系,但是他們都屬于food,于是就呈現出一種繼承關系。

然后定義粵菜類和川菜類:
public abstract class YueCai extends Food {

    public YueCai() {
        type = "YueCai";
    }
}
public abstract class ChuanCai extends Food {

    public ChuanCai() {
        type = "ChuanCai";
    }
}

因為他們是food類的子類,所以他們也含有food類的pic()和cook()方法。
既然要寫成菜譜,那么我們是否應該有一個專門來寫菜譜的人。

接著我們來定義cooker類
import java.util.List;

public class Cooker {

    private List<Food> foods = null;
    public Cooker() {
    }

    public void addFood(Food food) {
        foods.add(food);
    }

    public void write() {
        StringBuffer cookBook = new StringBuffer();
        for(Food food : foods) {
            cookBook.append(food.cook());
        }
    }
}

這里的cooker類,就是統一管理的類,首先是維護了一個List,類型是Food類,Food是抽象類,就是告訴大家,我這里要裝的菜肴,但具體是什么菜,你實際放什么菜那就是什么菜,我這里不關心。
然后定義了add方法,用于往List中填充內容,write()函數,就是寫菜譜了,循環遍歷List<Food>,依次調用Food的cook方法。這里就解決了,108道,每道菜不同,不需要我分別調用這108個類的方法,因為我在這里統一調用了抽象類Food的抽象方法cook(),但是這個方法是未實現的方法,所以它最終調用的是實現了這個方法的類。那么到底哪個類實現了該方法,而又是如何才能調用到的呢。

上面寫的所有的類都是代碼結構的搭建,說白了就是一群只知道說,不去做事的家伙

那么我們來定義踏實干活的人吧

public class MapoDouFu extends ChuanCai{

    public MapoDouFu() {
    }

    @Override
    public String cook() {
        return "mapoDoufu";
    }

    @Override
    public void pic() {
        
    }

}

public class YanjuChicken extends YueCai {

    public YanjuChicken() {
    }

    @Override
    public String cook() {
        return "YanjuChicken";
    }

    @Override
    public void pic() {
        
    }

}

我們這里定義了兩道菜的類,一個MapoDoufu,一個YanjuChicken。他們分別繼承了ChuanCai類和YueCai類,而ChuanCai類和YueCai類都是繼承自Food類,所以他們都是Food類的子類。并且都是Food類的最終實現類。

然后我們在合適的地方去調用Cooker的addFood()方法
Cooker cooker = new Cooker();
MapoDouFu mapoDouFu = new MapoDouFu();
cooker.addFood(mapoDouFu);
YanjuChicken yanjuChicken = new  YanjuChicken();
cooker.addFood(yanjuChicken);

這里就是java多態的體現,我們定義addFood()方法時,形式參數是Food類,但是在調用時實際傳入的Food類的子類MapoDoufu和YanjuChicken類。所以當我們去調用wirte()時,也將調用的實際傳入類的cook()方法。
這是簡單的對抽象類一個應用場景的介紹,同樣,接口也是可以這樣使用的。原理是一樣的,我這里就不復述了。

public interface Food {
    public void pic();
    public String cook();
}
public class YanjuChicken implements Food {

    public YanjuChicken() {
    }

    @Override
    public void pic() {
        
    }

    @Override
    public String cook() {
        return "YanjuChicken";
    }

}
public class MapoDoufu implements Food {

    public  MapoDoufu() {
    }

    @Override
    public void pic() {
        
    }

    @Override
    public String cook() {
        return "MapoDoufu";

}
public class Cooker {

    private List<Food> foods = null;
    public Cooker() {
    }
    public void write() {
        StringBuffer cookBook = new StringBuffer();
        for(Food food : foods) {
            cookBook.append(food.cook());
        }
    }
    public void addFood(Food food) {
        foods.add(food);
    }

}

至于type的作用,本篇沒有體現出來,而是想告訴大家要有抽象分類的思想。

這里只涉及到接口和抽象類最基礎的用法,還有回調,內部類等等的用法,這些東西也是很常用的,后續我會更新相關的文章,如有錯誤的地方,歡迎大家批評指正,不勝感激!如有疑惑的地方,也歡迎大家討論。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 01接口的概念 02接口的定義 03接口的實現類 04接口中成員變量的特點 05接口中成員方法的特點 06實現類還...
    葡小萄家的貓閱讀 637評論 0 1
  • 你很清楚的知道什么時候用抽象類,什么時候用接口么?p.s. 多文字預警! 1 抽象類和接口簡介 1.1 抽象類 ...
    Sharember閱讀 2,365評論 9 55
  • 1、面向對象的特征有哪些方面 1.抽象:抽象就是忽略一個主題中與當前目標無關的那些方面,以便更充分地注意與當前目標...
    michaelgong閱讀 842評論 0 1
  • 第一次使用簡書,還不太清楚它會在我的生活中扮演什么角色,但是我深知行動是解決問題的最好辦法。此刻,明天還要考試,我...
    jane1028閱讀 127評論 1 0
  • 2017年8月23日早6點半,聽完喜馬拉雅的易效能100講,我如以往打開印象筆記開始寫晨間日記。今天開心的看到晨間...
    田園成長閱讀 842評論 2 2