“接口”的概念和本质

经常看到调用这个接口,调用那个接口,这里的接口好像叫API,本质好像就是一函数,说调用函数不就行了吗,为什么要说调用接口?

还有一个地方出现“接口”这个词,就是面向对象编程的时候,那个interface,这也叫接口。这个接口和上面的接口有什么不同?

我好像总是对“接口”这个词理解不了,为什么叫接口,它的本质是什么?
想得到的答案主要从2个方面回答就可以了:
1、这个东西是什么,也就是概念。
2、这个东西有什么用,也就是拿来干嘛的,如果能举个例来说明就最好了。

阅读 19.4k
11 个回答

先讨论一下Interface这个单词,Interface可以翻译成两个意思:接口和界面。
实际上我个人认为接口和界面实际上是一个意思。界面可以认为是用户和计算机之间的接口,用户通过界面操作计算机。接口,可以理解为我要调用别人的代码,该如何调用。

接口不需要关注具体的内部实现,只需要关注我该怎么调用,就像用户通过界面来操作电脑是不需要关注电脑内部结构的。

再看API这个词,全称是Application Programming Interface,就是一个程序对外开放的接口,提供给用户调用,API文档用于描述接口如何调用。

另外Java的interface关键词,和上面所说的好像不一样,但是实际上理念还是差不多的,比如最重要的“接口不需要关注具体的内部实现,只需要关注我该怎么调用”。Java的interface中的方法都是没有实现的,但是却规定了如何去调用。

再谈谈硬件方面的接口,实际上也是Interface这个词。例如高清多媒体接口HDMI(High Definition Multimedia Interface),同样是用于双方对接,不需要关注双方的具体实现,例如HDMI输入设备可以是电脑、游戏机、电视盒等,输出设备可以是显示器、投影仪等。
图片描述

所以Interface这个词可以表达一个很泛的概念,可以这么理解:不需要关注具体实现,对外提供给用户如何调用的方式(即规范)。只要满足这两个条件可以认为就是Interface。

你说的这几个都是不同的东西,只是他们碰巧叫做接口罢了。
API:应用程序接口,所以可以简称接口。
interface:可以翻译成接口,所以也叫作接口了。

两个是不一样的东西,API的那个接口用来提供服务(天气,地区查询),interface的那个接口负责定义实现方法,但不指定方法的具体内容。

接口与函数不同,接口需要具备一些函数不具备的特性:数据传输格式(json/xml),通过GET/POST请求方式,等等。……虽然他们都是实现某一功能,但他们实际上是两种不同的东西,就好像

<?php 
echo 1;
function output(){
    echo 1;
};
output();
?>

output()和直接echo 都是输出,但他们还是不一样的。

copy from wiki:

应用程序接口(英语:Application Programming Interface,简称:API),又称为应用编程接口,就是软件系统不同组成部分衔接的约定

函数(或者说函数的定义)可以看成是代码和代码之间的一种API,连接调用代码和具体实现
OO中的interface可以看成OO模式中,描述对象能力的一种API,连接不同的实体类
诸如微信开放平台的“接口文档”是第三方程序和微信之间的API,连接第三方和微信

他的本质其实就是“约定”,你给我什么信息,我会帮你做什么事情,返回你什么结果,双方都遵守这个约定来进行实际的研发工作,从而提高协作的效率。

至于作用的话,因为现代软件开发越来越大型化、团队化、模块化,你越来越不可能一个人从头做到位,总有人在你后面为你提供数据,有人在你前面调用你实现一些功能,有人在你下面提供基础类库、常见操作的抽象。人和人之间的合作靠约定,程序员和程序员的协作靠的就是接口了。

接口的本质就是抽象出一些共性的方法形成一种约定或者说是规范。其目的是为了让程序之间或者程序中的模块之间的耦合性降低。
举个更加生活化的例子,也可以说接口为什么叫接口的例子:
我们生活中各种电器的插座插口其实只有几种类型(两口的或者三口的),这其实就属于一种接口,真是因为所有电器厂商都遵守了这个规范,我们在使用它们的时候就变得非常的方便。供电部门不需要知道电器内部走线是怎样的,而不论电器多么复杂,我们也不需要进行复杂的对接,只是插入插座,就能使用。
而编程中的接口也是一样的道理,编写模块A的人只要遵守特定的接口规定,那么我们就能很简单的将模块A接入与之配对的模块B,他们之间的关系就简化为了插头和插座的关系,并且模块A和模块B的编写者都可以不知道对方的代码,他们只需要知道接口的规定是啥即可。同样的道理,编写Windows程序的人并不需要知道真正运行这个程序的机器装的是什么显卡,内存有多大,他只需要让程序符合WindowsApi;而使用程序的我们,也并不需要知道程序的内部实现,不需要为程序做处理,只是很简单的拿来就用。

函数不是接口,函数的定义才是接口;
函数是接口的实现。

类(Class)也不是接口,类型(Type)才是接口;
类是接口的实现。

这两者有什么关系呢?
Interface是个很抽象的概念,翻译成接口实际上有点“不说人话”;
“人话”一点的翻译应该叫约定。

对于一个函数来说:

add:: Int -> Int -> Int

当我要调用它的时候,除了需要知道它的“语义”(它是干嘛的),还需要知道它的类型信息。
比如上面的Int -> Int ->Int,它表示接受2个Int类型的参数,返回一个Int类型的值。

这个时候,如果我写:

add "hello" " world!"

就是错的,因为我没有遵守“约定”;
有了这个约定,当你写的代码出现类型错误时,编译器或者IDE就能快速发现并提示你修正。

(这种情况下,私以为“调用接口”和“调用函数”并没有什么本质差别,只不过是说法不一样,毕竟函数声明和函数是绑在一起的)


如果局限在面向对象语言的Interface这个概念上,
Interface声明的“人话”版描述描述应该是“含有以下内容的实现的任何对象”。
为什么不用class?因为很多时候我们不需要知道一个Object的全部信息
我们只要知道它有某一个或者某几个特性就行了。

比如我们声明一个

interface ISpeakable {
 void Speak(string content)
}

那么,任何实现了ISpeakable的类(Class),我们都可以放心地speak("hello")
而不用担心它会出错,也不用关注它到底是一个Person还是一个Siri或者Contana。

这种情况下,使用接口的好处显而易见:

  • 接口是实现无关的,当你依赖一个接口而不是其实现时,你只需要关注对象的相同之处,而无需关注他们的差异。比如上面的Person和Siri都是可以Speak的,至于它们除此之外几乎没有什么共同点,你完全不需要知道。

  • 随之而来的,还有更好的复用性。你不需要分别实现MakePersonSpeak(Person p)MakeSiriSpeak(Siri s),你只需要一个MakeSpeak(ISpeakable cs),这对于整合流程,重用代码具有重大的意义。

  • 另外,依赖接口相对于依赖实现提的信息更少,也跟精确,提高了可读性。如果我需要操作一个Person对象,也许我是想让他Dance();但是如果我指定的是一个ISpeakable,不用说你也知道我想用Speak

无论什么概念的“接口”,本质上都是对接你并不了解的程序/服务时,所需要遵守的一系列格式/流程规定。

日常的“接口”就是个约定俗成的叫法,可以指代任何对接工作。不必死抠,你觉得顺口就可以。

而面向对象编程的“接口”,是一个明确的语义概念:接口(interface)代表若干个可以在类当中出现的公共成员的完整定义(包含名称、参数、类型等,但只包含定义,不允许包含实现)。

interface和class可以形成一对多的关系,一个interface变量的内容,可以任意代换为一个具体类。这样会带来以下的灵活性:

  • 一个任务有多种时空复杂度不同的做法时,只需改所对应的具体类,实现不同做法的代换

  • 多人协作时,先用接口约定互相的调用方法,然后各自编写自己的具体类,实现并行开发

  • 测试时,如果程序运行中需要交互的其他对象不容易获得,可以根据接口自行伪造(mock)一个类用于测试
    (这一点尤其重要!有些人认为1对1的类调用关系,就必然不需要接口了,这是错的,因为这个论调忽略了测试过程中可能存在mock的需求!)

而这一切的灵活性都只需要切换具体类,上层的调用方法无需变化。只要能够实现这个目的,做接口就是有价值的。

接口和函数很相似,功能几乎一样。一般情况下,函数多是内部调用,而接口可以在程序外部调用。比如移动端的app,数据肯定是从服务器来的,服务器给app端提供数据的通道或者门就是接口。这时你发现,接口和函数的不同在于,函数只有一个函数名,而接口还有其他的前缀,比如函数所在文件的路径。程序内部调用函数的时候,一般只用函数名就可以了,而接口需要加前缀。前缀类似于门牌号,比如调用a函数,程序里直接a()就行了。而接口则是localhost:3000/helloworld/a。函数就好像,在家里要喝水,直接拿水杯倒水就行。接口就是站在街上口渴了,不知道超市在哪。然后有个人告诉你在某大街15号有个超市,那里有水卖。不知道你理解了没有。

一个名词被各种解释,好吧,我就简单说个,对接入口

计算机科学是一门新科学,但里面很多的概念却取自已有的知识,而便于理解。
抛去计算机编程,接口可以理解为两个设备用于连接的地方,这个生活中到处可见,如电源接口,手机的耳机接口,USB等,都是这个概念,软件上也是这样,对于模块化的软件模块化之间,或者不同的应用之间。
如果你想为别人提供服务,那么提供服务和调用服务之间一定要有一个双方约定成熟的口令(人与人间就是语言)
对外的函数就是这个(硬件接口也是,不同的接口有不同的外形,协议等)

Interface-算是开发语言内部的,而不是对外的,也许翻译为界面你可能更容易理解,(或者你就关注face)
开发时你看到的仅是这个face,但运行时这个脸可能包含不同的内容,
如果人类的脸都有一个鼻子,两个耳朵,一张嘴等。但实际不同的人,各个器官是不一样的。

讨论不同开发中的接口定义,得出接口广泛定义

在面向过程和面向函数的调用的函数名,叫接口.
比如定义函数 int force(){ return "亚麻得"; }
根据语言函数的特点,使用返回值和回调和外部通信的。函数标识是唯一的。比如c中使用 返回值类型函数名参数来定义函数唯一标识。
如果加上模块dll。 那么接口 是由函数和模块定义的。比如在操作系统开发年代的,posix接口。成为unix和linux软件可以通用的基础

在面向对象中,比如定义动物对象,有两个派生对象,猫和狗。在动物对象中定义吃这个接口,猫和狗都有吃这个方法。对象和函数确定接口,与外部通信方法同样是返回值和回调

在WEB开发中,接口变成了一个URL,和网络通信中接口编程一个TCP或UCP协议.更加底层协议不研究。
本质来说域名也是IP+端口。比如www.baidu.com. 最终也是百度IP+端口的。网络编程也用大量的使用域名现象。个人认为WEB从侠义的定义也是网络编程的一种。
回到正题比如为了实现天气预报的客户端,调用了国人某些服务端的api接口,返回一个具有json或者XML,或者其他格式的数据。TCP通信中报文也是一种特点字符串格式。通过通信手法时候回调url.

总结随着时代发展 函数名变成了URL。但是特点没有变是特定类型操作一种方法调用。好比指针地址和IP地址.都是一个资源的标识符。这就是面向对象,多态,同样方法名,在不同对象中有不通实现。。。

电源有电源接口,usb是连接usb设备的接口,HDMI是连接显示器的接口。用途不一样,所以接口的种类也就有很多种。看似很有道理,其实是为自己的无能找一种借口罢了。看看iPhone有几个接口?充电你插那个接口?数据同步你插哪个接口?使用HDMI播放你插哪个接口?怎么都插一个接口呢?概念混淆吗?好像很受欢迎!所以,各种接口定义,其实就是没办法了,水平不够了,臣妾做不到了,搞个概念先顶一阵子吧。

编程语言也有接口,一般称为interface。那是在语言里设计的,被认为是最最接近人类思维的程序连接方式,也是一个独立功能最佳的表现形式。好了,现在多了层网络,还用这种最佳方式连接行不行?臣妾做不到!做不到怎么办?发明概念呗,什么restful,rpc等等先对付着,找帮所谓大牛吹着。以至于你谈API不谈这些,都不好意思告诉别人你是程序猿。

在网络中还像调用一个本地库一样调用网络资源不行吗?当然行!不行的是已经没人愿意谈论这些,因为谈这些显不出自己水平。还找出很多很多种理由否定。其中最经常谈到的理由就是自己的系统多么多么大,使用的语言多么多么多,臣妾真的做不到。掰着手指头数着自己在浏览器中使用了多少种语言?数来数去是一种。可臣妾还是做不到。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
宣传栏