前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >java组合接口 抽象出功能

java组合接口 抽象出功能

作者头像
废江_小江
发布2022-09-05 14:17:42
2940
发布2022-09-05 14:17:42
举报
文章被收录于专栏:总栏目

背景

今天,在写一个多线程的时候,犹豫了一下。为什么多线程可以其一是继承Thread类,然后重写run方法,表示是一个线程,然后Main中实例化出对象,调用start方法启动,其一就是实现Runnable接口,然后声明Thread的时候传入实现了Runnable接口的对象,也是构造出了一个线程。这两种方法有什么区别吗?脑海中回忆了之前看的java成神之路中的继承和组合的概念,遂灵光闪现,记下这篇文章。

例子

这个例子,主要在这篇博客上:https://www.cnblogs.com/vincent-blog/p/4389871.html我这里就不重复写代码了。

说的是有两个类,昆虫类和蜜蜂类。昆虫类中有两个方法,移动和攻击,并且在攻击的时候需要移动一次,于是,父类昆虫类中是这样写的:

代码语言:javascript
复制
public void attack() {
        move();  //假设昆虫在攻击前必须要先移动一次
        System.out.println("Attack");
    }

那么,如果蜜蜂继承昆虫类(事实也正是如此),问题就来了。蜜蜂再调用attack方法的时候,不仅仅自己的move了一次,父类昆虫也move了一次。但要知道,移动是不一样的,蜜蜂是fly,而其他一些昆虫就是走或者爬。这样肯定是不行的。

分析

首先,思考一下如何解决,不看那篇博客的话。蜜蜂继承昆虫这个不能改,这点毋庸置疑。那么继承了昆虫就有了昆虫的移动和攻击,移动方法没有问题。蜜蜂可以重写改方法,但是攻击呢?有人会说,昆虫父类中,别把移动丢进攻击里面。这样蜜蜂重写了移动,重写了攻击不就ok了? 但我想说,这样是不对的,攻击的功能就被你改掉了,攻击之前是有移动的,这是一个需求,或者说一组功能。那怎么办?

解决办法

将这个attack抽象出来!看下面的代码:

代码语言:javascript
复制
 Bee a = new Bee(1, "black", new AttackImpl("fly", "move"));
        a.attack();

蜜蜂在构造函数中传入了实现了attack接口的实现类,蜜蜂类中这样写:

代码语言:javascript
复制
class Bee extends Insect implements Attack {
    private final Attack attack;
 
    public Bee(int size, String color, Attack attack) {
        super(size, color);
        this.attack = attack;
    }
 
    public void move() {
        attack.move();
    }
 
    public void attack() {
        attack.attack();
    }
}

这样,将这个attack攻击和父类昆虫组合起来了,而不是单一的继承昆虫。

拓展

上面这个例子,在声明蜜蜂传入attack实现类,不正是我们声明多线程的第二种方式吗。所谓多线程,即多线程对象+多线程要做的事情。java中则是将多线程要做的事情(其实就是上面的attack功能)抽象出来,用一个接口来定义规则,然后通过实现类再次传回多线程对象。这样做的好处是什么?可以将其这个多线程要做的事情看作是一个资源,然后很多多线程都去解决这一个资源(即要做的事情)。典型的生产者和消费者就是这样。生产和消费者都要对同一个资源进行操作,即资源仓库。这时,你是生产者的多线程还是消费者的多线程,传入的都是这个资源仓库实现类。

题外

上面这些其实就是java通过组合+接口的方式实现了多继承。为什么说是多继承?你可以把上面的attack想象成为一个类,不就是bee蜜蜂类继承了昆虫和attack吗。事实上了,在c++中确实就是这样。java中不能实现多继承很简单,如果类B,C继承了A,当D继承了B,C的时候,在当D调用方法时就会混乱。至于java为什么不引入多继承?因为不太需要:在实际的应用中人们发现继承更多的只被用在两种场合扩充/改善基类,以及实现多态。对于前者,单继承足以;而对于后者,则真正需要的其实是纯抽象类,即只包含纯虚函数的基类。而对于这一种基类,由于其目的和普通的实例类已经有所不同,因此在java中将其改称为interface,即接口加以明确区分。

废江博客 , 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权 转载请注明原文链接:java组合接口 抽象出功能

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 背景
  • 例子
    • 分析
      • 解决办法
      • 拓展
      • 题外
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档