前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >接口的诞生

接口的诞生

作者头像
鸡先生
发布2022-10-29 17:22:04
2900
发布2022-10-29 17:22:04
举报
文章被收录于专栏:鸡先生鸡先生

接口的诞生

接口其实就是一种标准一种规范。 先从生活中的例子讲起,理解含义和概念后,再去理解程序会更容易理解一些。 生活中接口无处不在,比如著名的USB接口,大家可以试想一下,如果没有像USB这种统一的标准我们会有多麻烦。 拿电脑端来举例:

image
image

这台电脑只有A 接口,另一台电脑只有B 接口,一万台电脑就可以有一万个接口,那你该怎么去买数据线? 就算买了数据线,也只能用在一台电脑上换一个电脑就完全没用了。 而这只是数据线的其中一头,另一头的接口也没统一呢。

比如手机接口也不统。一万个手机就有一万个接口,这该有多麻烦。现在安卓和苹果,不能互用充电线,我们都觉得麻烦了,真要一个手机一种接口,那只怕心态崩了。如果没有一个统一的标准,那无论对设备厂商,还是对我们用户来说,都非常痛苦。所以统一标准和制定规范一定是各行各业都需要做也都想做的事情,那这个标准和规范就可以理解为接口。生活中的例子讲完,我们来延申到程序。

每项技术的产生,肯定是有其原因的。理解了技术的诞生经过,一般也就理解了技术本身。

那接口是如何诞生的呢?

image
image

假设现在是一个没有对象,只有基本数据类型和函数的世界,当我们的数据和函数多了维护起来就越发困难

image
image

于是我将其中一些有关联性质的数据和函数封装了起来,类和对象就这么诞生了,我只需要创建一个对象就拥有了特定的属性和方法,这些属性和方法都聚合在了一个实例上,维护起来比较方便。可还有一个问题,现在大多数类的属性和方法都差不多,完全没必要每次重新定义

image
image

于是乎我将这些重复的东西封装到一个类中,其他子类只需要复用它即可,继承就这么诞生了,子类继承父类之后,便拥有了父类的属性和方法,同时可以扩展自己的特性。

image
image

我们经常指定一个父类然后接收多个子类,在程序执行的时候,能自行发挥各种子类自己的特性,这一机制就是之前讲过的多态,很多时候我们发现父类完全没必要实现所有逻辑,也没必要创建父类对象,因为我们就是想让各种各样的子类来完成不同的逻辑。

image
image

这时候我们就可以将,父类的方法抽象出来,抽象类就这么诞生了,这里的抽象类其实已经有了标准和规范的意思,抽象方法就可以理解为一个对外的标准,子类就是这些标准的实现方,然后我们会发现,抽象类还不算彻底的抽象,因为它除了抽象方法外,还有成员属性,可我们很多时候,就是想指定一个纯粹的标准,让子类只去实现抽象方法,不想让子类再去继承别的东西。

image
image

于是乎我们将抽象类更进一步的抽象,接口就这么诞生了,接口只有方法没有成员属性,子类继承接口后,唯一能做的就是重写方法,所以说接口就是一种标准一种规范,它规定号方法模板后,子类都得按照这个来实现。说到这大家应该就能体会到接口在程序中的作用,就是定义方法让子类实现,然后供调用方调用。

映射到生活中子类就是设备厂商,接口调用方就是我们用户,只管使用,而不用操心各个设备的差异,概念性和比喻的东西讲完了,再来讲一讲,接口在程序中的具体运用:当我们想操作多个拥有共性的对象时,就可以用到接口

比如:我想打印一个数据集

代码语言:javascript
复制
    public static void printConllection(Collection collection){
	if(collection == null){
	     return;
	}
	System.out.println("数据数量"+ collection.size())
	System.out.println("数据"+ collection.size())
    }

    public static void main(String[] args){
	printCollection(new ArrayList());
	PrintCollection(new HashSet());
    }

就可以用到Java 的Collection接口,我将方法参数定义成Collection 别人就可以传任何 Collection 的子类进来了,ArrayList 可以,HashSet也可以,根本不用关心,数据是用哪个集合来存储的,Collection 有上百个子类别人爱用哪个用哪个,都不会影响到我的打印逻辑,就好像USB接口定义好后,你插U盘也好,手机充电线也好,这就是我们常说的面向接口开发

抽象类和接口的异同


image
image

首先我们知道抽象类和接口都是为了将方法进行抽象,然后让子类去实现

代码语言:javascript
复制
    public abstract class Animal{
	public abstract void eat();
   }

    public interface Runnable{
	public abstract void run();
    }

所以可以定义抽象方法就是这者第一个相同点。

在接口诞生中说过,这种类是没有必要创建实例对象的,所以第二个相同点就是不能创建本类对象,只能由子类去实例化子类对象。

两者最为明显的一个差异点,就是子类要扩展它们时使用的关键字不同,称呼不同但本质一样

代码语言:javascript
复制
// 继承抽象类
public class Dog extends Animal{}

// 实现接口
public class Thread implements Runnable {}

然后时抽象类可以去实现接口,而接口只能继承接口,不能继承类

代码语言:javascript
复制
public abstract class Animal implements A{}

public interface Runnable extends A,B,C{}

同时一个类最多只能继承一个父类,但可以实现多个接口。

代码语言:javascript
复制
public abstract class pet extends Animal implements A,B,C {}

所以当我们发现既可以用抽象类也可以用接口时,尽量去选择接口,这样子类的灵活度会更高

image
image

在接口的诞生我们说过,抽象类更进一步地抽象后就诞生了接口,接口比抽象类更纯粹,因为它没有成员属性,只有方法,子类实现接口后,唯一能做的就是重写方法,不像抽象类,子类继承抽象类后,连带父类的成员属性一起继承了。

代码语言:javascript
复制
  public abstract class Animal {
	protocted String name;

	public abstract void eat();
  }

  public interface Runnable {
	public static final String CRAB = "螃蟹";

	public abstract void run();
  }

抽象类可以定义成员属性,而接口不能定义成员属性,只能定义静态属性,而且只能用final 关键字定义静态常量,不能定义静态变量,接口还没有构造器,可以说是非常的纯粹了。

说白了接口就是一个只有方法和静态常量的类

这里有人可能会疑惑,抽象类都不能被实例化,还要个构造器有啥用,它的用处是限定子类的构造行为。 比如:抽象类可以将构造器定义好几个参数,子类要想实例化则必须想办法传入这几个参数

代码语言:javascript
复制
    public abstract class Animal{
	protected String name;
	protected Animal(String name){
	    this.name=name;
	}

	public abstract void eat();
    }

    class Dog extends Animal{
	public Dog(String name) {
	   super(name);
	}

	@Override
	public void eat() {
	    System.out.println(name + "要开吃了~");
	}
    }

两者异同就说完了,额外说明一些版本之前的差异 其实接口在Java8 之前更加纯粹,那时接口只能定义抽象方法,不能自己实现方法,也不能定义静态方法,到了Java 8才可以定义静态方法以及可以用 default 关键字来实现方法,这里不要死记硬背,一定要去理解 Java 设计者背后的意图,为什么突然在Java 8就加了这个特性呢?因为Java 8 许多原有的接口,新增了很多方法,这些新增的方法会影响到之前的子类如果你继承了某个接口,突然接口新增了一个方法,而你没有去实现,你的子类就会编译失败,为了保证向下兼容性,Java 8就推出了default关键字,被default关键字修饰的方法就不是抽象方法了,也就不会强制要求已有的子类去实现方法,default方法出现后,大家发现还挺好用,就大量在接口中去实现一些默认逻辑,可是一个方法中实现复杂逻辑,就会导致代码难以维护,于是Java 9又推出了一个新特性,那就是能在接口中,定义private 方法,这样就可以将一些内部逻辑拆开了,可以发现越到后面抽象类和接口的差异也就越小。

总结

抽象类(abstract class)

接口(interface)

定义

包含抽象方法的类

主要是抽象方法和静态常量的类

组成

构造器、抽象方法、普通成员方法、成员变量、静态方法、静态常量、常量

静态常量、抽象方法、default 方法、静态方法(Java8)私有方法(Java9)

使用

子类继承抽象类(extends)

子类实现接口(implements)

关系

子类只能继承一个抽象类,抽象类可以实现多个接口

子类可以实现多个接口,接口不能继承类,但可以继承多个接口

选择

如果需要继承父类的成员变量,或需要控制子类的实例化,则选抽象类

优先选择接口,避免单继承的局限性

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

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

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 接口的诞生
  • 抽象类和接口的异同
  • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档