java基础知识之接口---超详细(保姆级)

今天我们聊聊java基础知识中的接口,接口这个名字听起来有些抽象,没错接口其实就是抽象的,大家这时候就有疑问了,抽象类不能用么,为什么又出现一个接口的概念,让人真的觉得繁杂,前几篇我给大家说过,任何一项新技术的产生都是为了方便简单的实现某种目的。

那么说这么多还是没明白接口是干啥的呀,接口其实将实现功能范围扩大了,比如马儿会跑,汽车也会跑,跑这个动作是不同种类之间实现的,比如马儿是动物大类中的,汽车是机械大类中的,汽车和马儿都不在同种大类范围下,那么抽象类范围小点相当于同种类中不同对象对方法的不同实现,比如动物类下小猫小狗都实现跑这个动作。

抽象类类比:

接口类比:

从上边两个图片可以看出,其实接口的出现就是将类的实现范围扩大了,那么大家思考个问题,接口能像普通类一样实现接口之间的继承吗?答案是可以的,但是接口不是类,类只能实现单继承,而接口可以实现多继承。

接口间的继承

假设我们有一家公司,公司有DevOps (运维)、Tester (测试)、Developer (开发)和ProductManager (产品经理)。

然后,我们让ProductManager (产品经理)接口继承DevOpsTesterDeveloper三个接口,形成多继承。

DevOps(运维)接口:

csharp 复制代码
public interface DevOps {

    void deployApp(); // 部署应用
    default void handleIncidents() { // 处理事故
        System.out.println("运维人员处理事故...");
    }
}

Tester(测试)接口:

csharp 复制代码
public interface Tester {
    void exeTests(); // 执行测试
    default void reportBugs() { // 报告缺陷
        System.out.println("测试人员报告系统缺陷...");
    }

}

Developer(开发)接口:

csharp 复制代码
public interface Developer {

    void writeCode(); // 编写代码
    default void refCode() { // 重构代码
        System.out.println("开发人员重构代码...");
    }

}

ProductManager(产品经理)接口:

csharp 复制代码
public interface ProductManager extends DevOps, Tester, Developer{
    void gatherRequirements(); // 收集需求
    // 默认方法 - 协调不同团队
    default void coordTeams() {
        System.out.println("产品经理协调开发、运维、测试...");
    }

}

我们会发现ProductManager (产品经理)接口继承了三个父接口,DevOps (运维)、Tester (测试)、Developer (开发),说明产品经理三个父接口的6个方法还有自己的一个抽象方法和一个默认方法,那么产品经理就有8个方法,这个时候还不能直接的使用接口中的方法,需要有实现类来实现产品经理这个接口,通过实现类创建相关类对象并对接口的抽象方法进行重写,这时候接口中的默认方法和重写的方法就可以被调用了,其实接口中定义的方法就像一颗子弹,没有枪是无法发挥其本身的威力的,那么接口的实现类就是子弹的发射器,就是枪。

接口的实现

我们让TechManager (技术总监)去实现ProductManager(产品经理)的这个接口。

typescript 复制代码
public class TechManager implements ProductManager{
    private String name;

    public TechManager(String name) {
        this.name = name;
    }

    // 实现ProductManager接口的方法
    @Override
    public void gatherRequirements() {
        System.out.println(name + " 产品经理收集需求抽象方法重写.");
    }

    // 实现DevOps接口的方法
    @Override
    public void deployApp() {
        System.out.println(name + " 运维部署应用抽象方法重写.");
    }

    // 实现Tester接口的方法
    @Override
    public void exeTests() {
        System.out.println(name + " 测试抽象方法重写.");
    }

    // 实现Developer接口的方法
    @Override
    public void writeCode() {
        System.out.println(name + " 开发写代码抽象方法重写.");
    }

    // 重写默认方法以提供特定实现
    @Override
    public void coordTeams() {
        System.out.println(name + " 技术总监重写产品经理协调团队默认方法 .");
    }
}

测试代码:

csharp 复制代码
public class StartDemo {
    public static void main(String[] args) {
        // 创建技术总监实例
       TechManager pm = new TechManager("Tom");

        System.out.println("=== 产品经理职责 ===");
        pm.gatherRequirements();
        pm.coordTeams();
        System.out.println("=== 运维技能 ===");
        pm.deployApp();
        pm.handleIncidents(); // 使用继承的默认方法
        System.out.println("=== 测试技能 ===");
        pm.exeTests();
        pm.reportBugs(); // 使用继承的默认方法

        System.out.println("=== 开发技能 ===");
        pm.writeCode();
        pm.refCode(); // 使用继承的默认方法
    }

}

测试代码运行效果:

我们看到实现类实现了产品经理的接口,而产品经理接口继承了3个接口的所有方法,则TechManager (技术总监)这个类要重写DevOps (运维)、Tester (测试)、Developer (开发)ProductManager (产品经理)的所有抽象方法,那么接口中有了抽象方法还要默认方法干啥?接口中默认方法是为了如果有多个实现类中有相同的行为,那么避免重复在实现类中写出冗余方法,这个就是类去实现接口的意义,如果这个类不想重写接口中的抽象方法的话,这个类也只能以抽象类的形式存在,看到这的朋友们是不是在接口中没有看到属性?其实接口中的属性可以理解为不可更改常量,这个通常以 " public static final int x = 1"的形式存在,这样定义避免了多继承中属性的不确定性,这个接口常量相当于全局统一。

接口与抽象类

在实际应用中我们应该如何在接口和抽象类中进行选型:

其实大部分实际的应用中都是接口和抽象类组合使用,这样可以提高代码的灵活性和复用性,组合使用使得代码既有统一契约又有共享实现的特点,接下来我们看看接口和抽象类组合的例子,加深一下对接口和抽象类组合的理解深度。

我们有一个接口Switchable ,一个实现接口的抽象类AbstractSwitch ,一个具体类Light 继承抽象类去实现具体的行为。

Switchable接口:

csharp 复制代码
public interface Switchable {
    void turnOn();
    void turnOff();
    boolean status();
}

AbstractSwitch抽象类:

typescript 复制代码
public abstract class AbstractSwitch implements Switchable{
    protected boolean status = false;

    @Override
    public void turnOn() {
        status = true;
        System.out.println("设备开启...");
    }

    @Override
    public void turnOff() {
        status = false;
        System.out.println("设备关闭...");
    }

    @Override
    public boolean status() {
        return status;
    }

    // 抽象方法 - 由子类实现具体行为
    protected abstract void deviceAction();
}

Light具体类:

typescript 复制代码
public class Light extends AbstractSwitch {
    @Override
    protected void deviceAction() {
        if (status()) {
            System.out.println("设备灯亮...");
        } else {
            System.out.println("设备灯关闭...");
        }
    }

    @Override
    public void turnOn() {
        super.turnOn();
        deviceAction();
    }
    @Override
    public void turnOff() {
        super.turnOff();
        deviceAction();
    }
}

测试代码:

typescript 复制代码
public class StartDemo1 {
    public static void main(String[] args) {
        Switchable light = new Light();
        light.turnOn();
        light.turnOff();
    }

}

运行测试代码的效果:

从上面我们可以看出接口Switchable 定义了设备应该具备的基本操作(契约),抽象类AbstractSwitch 实现了接口Switchable 并对接口Switchable 中的抽象方法进行了重写,AbstractSwitch 提供了开关状态的通用实现,但留下了 deviceAction() 方法待具体实现,具体类对deviceAction() 进行了重写实现具体功能。

好了,接口部分的知识就给大家分享的到这里了,谢谢大家的观看与支持,下期我们再见。

相关推荐
han_6 小时前
前端高频面试题之Vue-router篇
前端·vue.js·面试
ShineWinsu11 小时前
对于数据结构:链式二叉树的超详细保姆级解析—中
数据结构·c++·算法·面试·二叉树·校招·递归
沐怡旸11 小时前
【穿越Effective C++】条款20:宁以pass-by-reference-to-const替换pass-by-value——参数传递的效率与语义
c++·面试
soda_yo11 小时前
搞不懂作用域链?这篇文章让你一眼秒懂!
javascript·面试
沐怡旸12 小时前
【底层机制】Ashmem匿名共享内存:原理与应用深度解析
android·面试
一名机电研究生14 小时前
华为、阿里巴巴、字节跳动 100+ Linux面试问题总结(一)
linux·华为·面试
张彦峰ZYF18 小时前
高并发优惠权益聚合接口的优雅实现(含超时控制 + 来源标识 + Fallback 降级)
java·后端·面试
Sailing19 小时前
🔥 React 高频 useEffect 导致页面崩溃的真实案例:从根因排查到彻底优化
前端·react.js·面试
byte轻骑兵19 小时前
【安全函数】C语言安全字符串函数详解:告别缓冲区溢出的噩梦
c语言·安全·面试
程序员爱钓鱼20 小时前
Python 实战:如何读取多格式 Excel 并实现跨表匹配合并(支持 XLS / XLSX)
后端·python·面试