Table of Contents:
- The lead-up
- Deadly Diamond of Death
- How interfaces solve the diamond problem?
- The idea behind interfaces
- The practical use of interfaces while writing software
- To conclude。。
- Official Oracle Documentation
The lead-up
当我在大学学习Java时,我不了解接口的用法。
您不能在接口内定义函数。 您只能声明它们。 您必须有一个实现接口的类来定义其功能,然后使用它们。
太疯狂了! 我认为这是毫无价值的废话。 我可以正常编写类及其功能。 我为什么要在一个地方声明它们,在另一个地方定义。
我什至不需要声明它们。 只需在类中正常编写我的函数即可。 这是完全多余的。
我感到困惑和好奇,问我的老师为什么我需要实现一个接口。
她几乎立即说,接口使您可以实现多重继承,而普通的类则不能—教科书回答了类和接口之间的区别。
我当时是这样吗? 即使我的类可以一次实现多个接口,它们都不包含函数定义。
他们都将毫无用处。 我可以全部删除它们并编写类而不执行它们。 无论是单个还是多个,使用接口都能带来什么优势?
我的老师没有答案。
由于缺乏正确的答案,我和我的大多数(如果不是全部)朋友都辞职了,以接受界面是某种神秘的人工产物。 给出正确的咒语,这将有助于我们操纵时空连续体,撕裂Java生态系统的结构并使用多重继承-我们错误地禁止了这种成果。
同时,在工程过程中,我们给出了与老师给我相同的答案。 并在我们的笔试中写下相同的内容。
虽然有些感觉。 我永远也消化不了。
直到后来,当我涉足Android时,我才真正了解了接口的用途-作为一种合同,让您强制执行,与您一起使用的类表现出某些行为.
我仍然遇到人们,他们对接口的主要理解是允许Java进行多重继承。
这太荒谬了-当我问你两者之间有什么区别时,接口支持多种继承而类却不支持。
这就像狗和马之间的区别是狗在马附近咆哮。
虽然确实如此,但您必须了解,狗和马是根本不同的动物!
如果您对马的理解是对狗的理解。 那个男孩! 您将在农场里度过一个愉快的时光!
Deadly Diamond of Death
首先,让我们理解为什么Java中不允许多重继承。
考虑有一类“动物”。 所有动物都会发出Noise()。
我们从该类派生两个子类-“马”和“狗”。 它们都覆盖了makeNoise()行为。
马通过嘶叫来制造Noise()。 狗通过吠叫来制造Noise()。
现在假设,出于种种不可思议的原因,一个疯狂的科学家决定将马和狗的基因混合在一起,并创造出一种新的动物-霍格斯。
当Horgs makeNoise()时,它们会吠吗? 还是会邻居?
这是面向对象编程中的臭名昭著的钻石问题(又名致命钻石死亡)。
Java不支持类的多重继承,这仅仅是因为一起继承多个类是有问题的.
如果一个类继承了其他多个类,并且这些类包含具有相同签名的函数,则会产生歧义-当我使用继承(派生的)类的实例调用所述函数时,它应如何表现?
在来自多个继承的类的许多函数定义中,应该考虑哪些?
以及如何控制何时使用哪个定义?
C++ tries to handle the Diamond problem using virtual inheritance and scope resolution.
我不是一个C ++人. 而且我不了解虚拟继承的工作原理.
但是,据我了解,它需要先验知识,即某个功能可能会涉及多重继承。. 而且需要特别处理.
现在对我来说很奇怪. 我没有找到很多关于该主题的文章. 因此,也许没有多少人使用它. 但是,如果您有任何建议,请务必向我推荐有关该主题的任何材料.
How interfaces solve the diamond problem?
他们没有。
就像我说的那样,它们不是允许多重继承的机制。 只是因为接口没有方法定义,所以它们没有有钻石问题。
这就是为什么允许您实现多个接口的原因。 就这样。
但是,使用接口来实现多重继承的观点是错误的,与事实相去甚远。
The idea behind interfaces
认为你是国王。 您有一个已经达到结婚年龄的漂亮女儿。
来自邻国的许多王子渴望与您的女儿结婚。 但是,您要牢记一些基本标准,在他们被考虑与您的女儿结婚之前,他们应该满足。
- 王子应该可以打架. 'cause that's a necessary skill to have for a prince
- The Prince should like reading books. 因为书中包含知识. 而且您希望您的女son受到良好的教育和明智.
- The Prince should be able to speak Klingon. 因为那是一个上等人的标志.
您将这些要求写下来放在大横幅上,并将其放在城堡大门上方。
如果王子来满足所有这些条件,则网守将授予他“巴达斯王子”徽章并将其送入。
但是,如果王子不满足这些要求,城堡的看门人甚至都不会允许他进入。
现在,这正是接口背后的想法.
带有要求的标语是“ Badass Prince”的界面. 通过对预期的Prince实施这些要求,您实际上是在要求他们实现“ Badass Prince”界面.
Thus stating, that if a Prince is not a 'Badass Prince' (as defined by your interface), they're not eligible to marry your daughter.
The practical use of interfaces while writing software
如果您知道某个类实现了一个接口,那么您就知道该类包含该接口中声明的方法的具体实现,并且可以保证能够安全地调用这些方法。.
— StackOverflow answer
通常,不同的团队会共同开发产品。 他们可以使用不同的功能或集成在一起以形成最终产品的细分市场。
在这种情况下,很明显,团队内部将存在某些相互依存关系。
例如,我们正在构建一个电子商务网站。 一个团队正在开发“添加到购物车”功能(结帐之前的过程)。 另一个团队正在研究在线支付系统(结帐后的过程)。
在购物车团队完成并测试其功能之前,我们绝对不能让在线支付团队处于闲置状态。
但是,如果两个团队都开始并行处理其功能,那么我们如何确保将在线支付与购物车集成在一起? 最后,两个功能应该结合在一起形成最终产品,对吗?
例如,在线支付团队需要在成功付款后清除购物车。 但是,由于购物车尚未准备好,付款团队将如何做呢? 他们应该调用什么功能? 他们应该将哪些参数传递给它? 如果购物车团队根本不实现这种功能怎么办? 相反,您必须编写逻辑以分别从购物车中删除每种产品?
为了缓解此类问题,两个团队都必须就其各自功能的技术要求进行头脑风暴,并实现相互依赖。 完成后,两个团队都可以设计适当的界面。
例如,团队决定在结帐时,购物车系统将向付款系统提供MyCart对象。 该MyCart类必须实现具有以下方法的Cart接口:
1. void addProduct(Product product)
2. Product removeProduct(integer productId)
3. List<Product> getProductsFromCart()
4. boolean emptyCart()
如果购物车系统提供的对象不是来自实现购物车接口的类,则支付系统将抛出异常。
if(!(myCart instanceof Cart)){
throw new Exception("Expected an instance of Cart");
}
Due to the principle of abstraction in object oriented programming, the payments-team does not need to know how the emptyCart method works. 他们只需要知道:
- 它存在
- 打算按照自己的意愿去做(清除购物车中的所有产品)
- 调用方法(要传递的参数以及返回的期望值)。
在这些接口中,接口负责点1和3。点2留给人类理解。
基本上,通过要求购物车团队实现购物车界面,付款团队说,
“嘿,车队,
我们并不关心您这一边的逻辑和实现。
但是,我们要求您传递给我们的对象中必须具有某些功能。 而且我们以一种非常特定的方式要求它(带有某某名称,某某参数,某某值返回)。
请严格按照规定执行这些操作,以便我们可以将您的购物车系统插入我们的付款系统。 我们可以进行无缝集成。”
这只是使用接口时的一个简单示例。 可能还有更多。 但是,我希望它可以帮助您了解界面在软件开发中所起的重要作用。
如果您能想到更多示例,请在评论中让我知道。
在计算中,接口是一个共享边界,计算机系统的两个或多个独立组件在该共享边界上交换信息.
...
因此,接口是类型定义。 可以交换对象的任何地方(例如,在函数或方法调用中),可以根据其实现的接口或基类之一来定义要交换的对象的类型,而不用指定特定的类.
— Wikipedia
另外,许多人将接口与法律合同相关联。 这是因为接口基于两方之间的相互协议; 关于一方如何使用另一方的服务。
您符合合同中的要求。 您将享受我们不间断的服务。
您无法履行合同条款,我们将不再为您服务。
合同就像人与人之间的承诺. 这是两个或多个人或组织之间做某事的一种理解,一种交易.
— Arts + Law article
To conclude..
- 多重继承是有问题的。
- Java新手经常错误地将接口与多重继承相关联。 那不是他们的目的。
- 接口实际上是一个非常强大的构造,可让您定义软件组件的需求。 它还使您可以强制与您交互的其他软件组件满足这些要求。
Official Oracle documentation
Oracle提供了一些非常出色的接口文档。 因此,请查看以下链接并四处看看。