抽象类和接口的使用

2017-12-13  本文已影响0人  IT废柴

开篇废话

入职后一直研究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.jianshu.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的作用,本篇没有体现出来,而是想告诉大家要有抽象分类的思想。

这里只涉及到接口和抽象类最基础的用法,还有回调,内部类等等的用法,这些东西也是很常用的,后续我会更新相关的文章,如有错误的地方,欢迎大家批评指正,不胜感激!如有疑惑的地方,也欢迎大家讨论。

上一篇下一篇

猜你喜欢

热点阅读