美文网首页
抽象类和接口的使用

抽象类和接口的使用

作者: IT废柴 | 来源:发表于2017-12-13 09:44 被阅读0次

开篇废话

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

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

相关文章

  • Spring的学习

    接口和抽象类? 抽象类和接口的区别在于使用动机。使用抽象类是为了代码的复用,而使用接口的动机是为了实现多态性。1....

  • Android_开发_Day12_抽象类和接口

    Android_开发Day12抽象类和接口 目的: 知道什么是抽象类,什么是接口,学会抽象类的使用,与接口的使用。...

  • 抽象类和接口的区别

    以下两篇文章介绍了接口和抽象类的概念接口概念抽象类概念 抽象类和接口的区别: 抽象类:需要使用abstract关键...

  • 接口和抽象类的区别

    接口和抽象类有什么区别 你选择使用接口和抽象类的依据是什么? 接口和抽象类的概念不一样。接口是对动作的抽象,抽象类...

  • kotlin 接口和抽象类的使用

    一、接口的使用(1) 二、接口和抽象类的使用(2)

  • 接口和抽象类该如何取舍

    抽象类和接口的区别在于使用动机。使用抽象类是为了代码的复用,而使用接口的动机是为了实现多态性。 “面向接口编程”中...

  • 抽象类 vs 接口

    抽象类和接口的区别在于使用动机。使用抽象类是为了代码的复用,而使用接口的动机是为了实现多态性。

  • 代理(委托)模式

    主题抽象类或接口 主题抽象类或接口实际类 主题抽象类或接口代理类 使用

  • 建造者模式

    建造者抽象类或接口 建造者抽象类或接口实现类 产品抽象类或接口 产品抽象类或接口实现类 使用

  • Java 接口 抽象类 枚举

    接口 使用接口对行为进行抽象 接口: 抽象类 抽象类是用来捕捉子类的通用特性的,包括属性及行为。 抽象类: 抽象类...

网友评论

      本文标题:抽象类和接口的使用

      本文链接:https://www.haomeiwen.com/subject/xjwnixtx.html