gpr*_*our 63 java oop inheritance interface multiple-inheritance
我对这件事情仍然有些困惑.我到现在所发现的是
(这里已经提出了类似的问题,但我还有其他一些观点.)
接口是仅抽象方法和最终字段的集合.
Java中没有多重继承.
接口可用于在Java中实现多重继承.
继承的一个优点是我们可以在派生类中使用基类代码而无需再次编写它.可能这是继承在那里最重要的事情.
现在..
Q1.由于接口只有抽象方法(没有代码)所以我们怎么说如果我们实现任何接口那么它是继承?我们没有使用它的代码.
Q2.如果实现接口不是继承,那么如何使用接口来实现多重继承?
Q3.无论如何使用Interfaces有什么好处?他们没有任何代码.我们需要在我们实现它的所有类中反复编写代码.
那么为什么要制作接口呢?
注意:我找到了一个接口有用的案例.它的一个例子就像在Runnable接口中我们有public void run()方法,我们在其中定义线程的功能,并且内置编码,该方法将作为单独的线程运行.所以我们只需要编写线程中的代码,Rest是预定义的.但是这个东西也可以用抽象类和所有东西来实现.
那么使用接口的确切好处是什么?我们使用Interfaces实现了多重继承吗?
Tom*_*icz 38
Q1.由于接口只有抽象方法(没有代码)所以我们怎么说如果我们实现任何接口那么它是继承?我们没有使用它的代码.
我们做不到.接口不用于实现多重继承.他们用更安全但更弱的构造来代替它.注意关键字implements而不是extends.
Q2.如果实现接口不是继承,那么如何使用接口来实现多重继承?
他们不是.使用接口,单个类可以具有多个" 视图 ",不同的API或功能.例如,A类可以Runnable和Callable在同一时间,而这两种方法都有效地做同样的事情.
Q3.无论如何使用Interfaces有什么好处?他们没有任何代码.我们需要在我们实现它的所有类中反复编写代码.
接口是一种多重继承,没有后者引入的问题(如Diamond问题).
接口的用例很少:
对象实际上有两个身份:一个Tank 是既是Vehicle和Weapon.您可以使用Tank前者或后者所在的实例(多态).这在现实生活中很少出现,实际上是多重继承更好(或特征)的有效例子.
简单的职责:Tank游戏中的对象实例也Runnable允许您在线程中执行它并ActionListener响应鼠标事件.
回调接口:如果对象实现了给定的回调接口,则会通知它有关其生命周期或其他事件的信息.
标记接口:不添加任何方法,但可以通过instanceof发现对象功能或愿望轻松访问.Serializable和Cloneable就是这样的例子.
你正在寻找的是特质(就像在Scala中一样),遗憾的是在Java中不可用.
gpr*_*our 22
接口是最终静态字段和抽象方法的集合(Newly Java 8增加了对在接口中使用静态方法的支持).
接口是在我们知道必须完成某项任务的情况下进行的,但是如何完成它可能会有所不同.换句话说,我们可以说我们实现了接口,以便我们的类开始以特定的方式运行.
让我用一个例子来解释,我们都知道动物是什么.像狮子是动物,猴子是动物,大象是动物,牛是动物,等等.现在我们知道所有动物都吃东西睡觉了.但每只动物吃东西或睡觉的方式可能不同.像狮子一样,通过狩猎其他动物来吃东西,就像母牛吃草一样.但两人都吃.所以我们可以有这样的伪代码,
interface Animal {
public void eat();
public void sleep();
}
class Lion implements Animal {
public void eat() {
// Lion's way to eat
}
public void sleep(){
// Lion's way to sleep
}
}
class Monkey implements Animal {
public void eat() {
// Monkey's way to eat
}
public void sleep() {
// Monkey's way to sleep
}
}
Run Code Online (Sandbox Code Playgroud)
根据上面提到的伪代码,任何能够进食或睡觉的东西都会被称为动物,或者我们可以说所有动物都必须吃饭和睡觉,但吃饭和睡觉的方式取决于动物.
在接口的情况下,我们只继承行为,而不是类继承的实际代码.
Q1.由于接口只有抽象方法(没有代码)所以我们怎么说如果我们实现任何接口那么它是继承?我们没有使用它的代码.
实现接口是另一种继承.它与类的继承类似,因为继承子类从基类中获取要重用的实际代码.
Q2.如果实现接口不是继承,那么如何使用接口来实现多重继承?
据说是因为一个类可以实现多个接口.但我们需要了解这种继承与类的继承不同.
Q3.无论如何使用Interfaces有什么好处?他们没有任何代码.我们需要在我们实现它的所有类中反复编写代码.
实现一个接口会强制它必须覆盖所有抽象方法的类.
吻
我已经搜索了几天,试图了解接口并且似乎阅读相同的通用帮助; 我并不是要贬低这些贡献,但我认为灯泡只是点击了所以我很喜欢:))
我更喜欢保持简单愚蠢,因此将提供我新发现的界面视图.
我是一个随便的编码器,但我想发布我在VB.NET中编写的代码(其他语言的原理是相同的),以帮助其他人理解接口.
如果我错了,请在后续评论中告诉其他人.
说明
表单上的三个按钮,单击每个按钮可以保存对接口变量(_data)的不同类引用.不同类引用到接口变量的整点是我不理解的,因为它似乎是多余的,然后它的功能随着msgbox变得明显,我只需要调用SAME方法来执行我需要的任务,在此case'GetData()',它使用当前由接口引用变量(_data)保存的类中的方法.
因此,我想获取我的数据(来自数据库,网络或文本文件),它只使用相同的方法名称 ; 该实现背后的代码......我不在乎.
然后使用接口更改每个类代码很容易,没有任何依赖性...这是OO和封装的关键目标.
何时使用
代码类,如果您注意到用于方法的相同动词,例如'GetData()',那么它是在该类上实现接口并将该方法名称用作抽象/接口的良好候选者.
我真诚地希望这可以帮助这个困难原则的老板.
Public Class Form1
Private _data As IData = Nothing
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
_data = New DataText()
MsgBox(_data.GetData())
End Sub
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
_data = New DataDB()
MsgBox(_data.GetData())
End Sub
Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
_data = New DataWeb()
MsgBox(_data.GetData())
End Sub
End Class
Public Interface IData
Function GetData() As String
End Interface
Friend Class DataText : Implements IData
Friend Function GetData() As String Implements IData.GetData
Return "DataText"
End Function
End Class
Friend Class DataDB : Implements IData
Friend Function GetData() As String Implements IData.GetData
Return "DataDB"
End Function
End Class
Friend Class DataWeb : Implements IData
Friend Function GetData() As String Implements IData.GetData
Return "DataWeb"
End Function
End Class
Run Code Online (Sandbox Code Playgroud)
老问题。我很惊讶没有人引用规范来源:Java: James Gosling的概述,设计模式:四人组的可重用面向对象软件的元素或Joshua Bloch 的Effective Java(以及其他来源)。
我将从引用开始:
接口只是对象响应的一组方法的规范。它不包括任何实例变量或实现。接口可以被多重继承(与类不同),并且它们可以以比通常的刚性类继承结构更灵活的方式使用。(高斯林,第 8 页)
现在,让我们一一回答你的假设和问题(我会主动忽略 Java 8 的特性)。
你看到abstractJava 接口中的关键字了吗?不。那么您不应该将接口视为抽象方法的集合。也许你被 C++ 所谓的接口误导了,它们是只有纯虚方法的类。按照设计,C++ 没有(也不需要)接口,因为它具有多重继承。
正如 Gosling 所解释的那样,您应该将接口视为“对象响应的一组方法”。我喜欢将界面和相关文档视为服务合同。它描述了您可以从实现该接口的对象中得到什么。文档应指定前置条件和后置条件(例如参数不应为空,输出始终为正,...)和不变量(不修改对象内部状态的方法)。我认为,这份合同是 OOP 的核心。
的确。
JAVA 忽略了 C++ 中许多很少使用、理解不足、令人困惑的特性,根据我们的经验,这些特性带来的痛苦多于收益。这主要包括运算符重载(尽管它确实有方法重载)、多重继承和广泛的自动强制。(高斯林,第 2 页)
没什么好补充的。
不,很简单,因为 Java 中没有多重继承。看上面。
这就是所谓的“实现继承”。正如您所写,这是重用代码的便捷方式。
但它有一个重要的对应物:
父类通常至少定义其子类的物理表示的一部分。因为继承将子类暴露于其父类实现的细节,所以常说“继承破坏封装”[Sny86]。子类的实现与其父类的实现如此紧密地联系在一起,以致于父类实现的任何更改都将强制子类更改。(GOF,1.6)
(在 Bloch 第 16 项中也有类似的引述。)
实际上,继承还有另一个目的:
类继承结合了接口继承和实现继承。接口继承根据一个或多个现有接口定义新接口。实现继承根据一个或多个现有实现定义新的实现。(GOF,附录A)
两者都extends在 Java 中使用关键字。您可能有类的层次结构和接口的层次结构。第一个共享执行,第二个共享义务。
接口的实现不是继承。是执行。因此关键字implements.
Java 中没有多重继承。看上面。
最重要的问题是:为什么要拥有多重继承?我可以想到两个答案:1. 为对象提供多种类型;2.重用代码。
在 OOP 中,一个对象可能有不同的类型。例如在 Java 中, anArrayList<E>有以下类型:Serializable, Cloneable, Iterable<E>, Collection<E>, List<E>, RandomAccess, AbstractList<E>, AbstractCollection<E>and Object(我希望我没有忘记任何人)。如果一个对象具有不同的类型,则不同的消费者将能够使用它而不知道它的特殊性。我需要一个Iterable<E>,你给我一个ArrayList<E>?没关系。但是如果我现在需要一个List<E>而你给我一个ArrayList<E>,那也没关系。等等。
你如何在 OOP 中输入对象?你以Runnable界面为例,这个例子非常适合说明这个问题的答案。我引用官方 Java 文档:
此外,Runnable 提供了使类处于活动状态而不是子类化 Thread 的方法。
重点是:继承是一种输入对象的便捷方式。你想创建一个线程?让我们子类化这个Thread类。你想要一个对象有不同的类型,让我们使用多重继承。啊。它在 Java 中不存在。(在 C++ 中,如果您希望一个对象具有不同的类型,则可以采用多重继承。)
那么如何为对象提供多种类型呢?在 Java 中,您可以直接键入您的对象。这就是您在implements为Runnable接口上课时所做的事情。Runnable如果您是继承的粉丝,为什么要使用?也许是因为你的类已经是另一个类的子类,比如说A. 现在你的类有两种类型:A和Runnable。
通过多个接口,您可以为一个对象提供多种类型。您只需要创建一个具有implements多个接口的类。只要你遵守合同,就可以。
这是一个很难的课题;我已经在打破封装时引用了 GOF。其他答案提到了钻石问题。您还可以考虑单一职责原则:
一个类应该只有一个改变的理由。(Robert C. Martin,敏捷软件开发、原则、模式和实践)
拥有一个父类可能会给一个类一个改变的理由,除了它自己的职责:
超类的实现可能会随着版本的不同而改变,如果发生了变化,子类可能会中断,即使它的代码没有被触及。因此,子类必须与其超类一起进化(Bloch,第 16 项)。
我再补充一个比较平淡的问题:当我试图在一个类中找到一个方法的源代码却找不到时,我总是有一种奇怪的感觉。然后我记得:它必须在父类的某个地方定义。或者在祖父母班。或者甚至更高。在这种情况下,一个好的 IDE 是一种宝贵的资产,但在我看来,它仍然是一种神奇的东西。与接口层次结构没有任何相似之处,因为 javadoc 是我唯一需要的东西:IDE 中的一个键盘快捷键,我就明白了。
继承豪威有以下优点:
在包中使用继承是安全的,其中子类和超类的实现在同一程序员的控制之下。在扩展专门为扩展而设计和记录的类时,使用继承也是安全的(第 17 条:继承的设计和记录或禁止它)。(布洛赫,第 16 项)
Java 中“专门为扩展而设计和记录”的类的一个示例是AbstractList.
但是 Bloch 和 GOF 坚持这一点:“优先组合而不是继承”:
委托是一种使组合像继承一样强大的重用方式 [Lie86, JZ91]。在委托中,处理请求涉及两个对象:接收对象将操作委托给它的委托。这类似于子类将请求推迟到父类。(GOF 第 32 页)
如果您使用组合,您将不必一次又一次地编写相同的代码。您只需创建一个处理重复的类,然后将此类的实例传递给实现该接口的类。这是重用代码的一种非常简单的方法。这有助于您遵循单一职责原则并使代码更具可测试性。Rust 和 Go 没有继承(它们也没有类),但我不认为代码比其他 OOP 语言更冗余。
此外,如果您使用组合,您会发现自己很自然地使用接口来为您的代码提供所需的结构和灵活性(请参阅有关接口用例的其他答案)。
注意:您可以与 Java 8 接口共享代码
最后,引用最后一句:
在令人难忘的问答环节中,有人问他 [James Gosling]:“如果你可以重做 Java,你会改变什么?” “我会离开课程”(网络上的任何地方,不知道这是不是真的)
Q1.由于接口只有抽象方法(没有代码)所以我们怎么说如果我们实现任何接口那么它是继承?我们没有使用它的代码.
不幸的是,在口语用法中,inheritance当一个类实现一个接口时,这个词仍然经常被使用,虽然它interface implementation是一个更好的术语 - IMO,该术语inheritance应该严格地用于具体或抽象类的继承.在像C++和C#这样的语言中,相同的语法(即Subclass : Superclass和Class : Interface)用于类继承和接口实现,这可能导致inheritance使用接口滥用字的扩散.Java有不同的语法extend荷兰国际集团的一类,而不是implement荷兰国际集团的接口,这是一件好事.
Q2如果实现接口不是继承,那么如何使用接口来实现多重继承?
您可以通过组合实现多重继承的"效果" - 通过在类上实现多个接口,然后为类中所有接口所需的所有方法,属性和事件提供实现.使用具体类执行此操作的一种常见技术是通过将实现"连接"到每个内部类实现来实现外部接口的类来实现"has-a"(组合)关系.(像C++这样的语言确实直接支持多个具体继承,但是会产生其他潜在问题,比如钻石问题).
Q3无论如何使用Interfaces有什么好处?他们没有任何代码.我们需要在我们实现它的所有类中反复编写代码.
接口允许现有的类(例如框架)与您的新类进行交互,而无需事先"看到"它们,因为它具有通过已知接口进行通信的能力.将接口视为合同.通过在类上实现此接口,您在合同中必须满足其所需的义务,并且一旦实现此合同,那么您的类应该能够与使用该接口的任何其他代码互换使用.
真实世界的例子
"现实世界"的例子是围绕特定国家的电壁式插座的立法和惯例(界面).插入插座的每个电器都需要满足当局为插座定义的规格(合同),例如线路,中性线和地线的定位,开/关开关的位置和颜色以及一致性通过interface接通电源时提供的电压,频率和最大电流.
将接口(即标准壁式插座)分离而不仅仅是将电线焊接在一起的好处是,您可以插入(和拔下)风扇,水壶,双适配器或明年发明的一些新设备,即使设计界面时该设备不存在.为什么?因为它符合界面的要求.
为何使用接口?
接口非常适合松散耦合类,并且是Uncle Bob的SOLID范例的主要内容之一,尤其是Dependency Inversion Principle和Interface Segregation Principles.
简单地说,通过确保类之间的依赖关系仅在接口(抽象)上而不是在其他具体类上耦合,它允许依赖性替换为满足接口要求的任何其他类实现.
在测试中,依赖项的存根和模拟可用于对每个类进行单元测试,并且类可以"依赖"该类与依赖项的交互.
这是一个非常古老的问题,java-8版本为界面添加了更多功能和强大功能.
接口声明可以包含
在接口中具有实现的唯一方法是默认和静态方法.
使用界面:
Strategy_pattern看看这个相关的SE问题代码示例,以便更好地理解概念:
我该如何解释Interface和Abstract类之间的区别?
回到你的问题:
Q1.由于接口只有抽象方法(没有代码)所以我们怎么说如果我们实现任何接口那么它是继承?我们没有使用它的代码.
Q2.如果实现接口不是继承,那么如何使用接口来实现多重继承?
接口可以包含静态和默认方法的代码.这些默认方法提供向后兼容性,静态方法提供帮助/实用程序功能.
你不能在java中拥有真正的多重继承,并且接口不是获取它的方法.接口只能包含常量.所以你不能继承状态,但你可以实现行为.
您可以使用功能替换继承.接口提供了多种实现类的功能.
Q3.无论如何使用Interfaces有什么好处?他们没有任何代码.我们需要在我们实现它的所有类中反复编写代码.
请参阅我的答案中的" 界面使用 "部分.
| 归档时间: |
|
| 查看次数: |
53996 次 |
| 最近记录: |