Java中的OOP:多态性和接口


在许多情况下,我的观察是候选人非常了解该主题。他们的理论知识很好。他们的回答质量表明,他们在核心Java的不同领域都有实际的工作经验,例如异常处理,集合框架,泛型和对象。他们或多或少对这些东西有一个清晰的认识。并且在许多情况下,他们知道更新版本中添加的新功能。

缺乏了解是由于对Java的许多关键领域缺乏了解,例如集合框架,多态性,接口,甚至是异常处理。

在本文中,我将讨论Java的两个核心功能-多态和接口。

多态性 由于多态性是面向对象编程的关键原理之一,因此始终围绕此主题存在疑问。

在面试中,我通常会问:“多态是什么?”

令人奇怪的是,在大多数情况下,得到的回答是:“ p olymorphism意味着许多形式。”

作为回应,接下来的问题通常是:“ W¯¯帽子你说的意思是‘多种形式?’”

接下来是事情变得有趣的地方。从那时起,我发现“多种形式”的概念因候选人而异。

我收到的最常见的答案是:“有两种类型的多态性:运行时多态性和静态多态性。方法重写是运行时多态性的一个示例,方法重载是静态多态性的一个示例。”

显然,他们知道为什么将方法重载称为“运行时多态性”,为什么将“方法重载”称为“静态多态性”。但是,很难从这些答案中得出关于“许多形式”的含义的结论。而且尽管方法重载和方法重写是多态的,但为什么 它们却是多态的呢?

method-overloading-overriding.jpg

这个问题的下一个最常见的答案是:“让我举一个例子来说明……”而用于解释它的例子再次是与前面说明的相同的方法重载和方法重载示例。

但是,在极少数情况下,候选人使用对象引用的概念来解释多态性。基本上,Java中多态性的最佳用途是能够通过使用父类引用来引用子类。在多态中,“许多形式” 是指对象或方法采取多种形式的能力。方法重载和方法重载基本上意味着Java中的一种行为,该行为使开发人员可以利用该原理。

下面是一个示例:

![polymorphism.png](/media/images/qa/2021/04/20/48b05c366d-polymorphism.png)

在上图中,Shape是一个接口(也可以是一个Class),具有一个抽象方法 draw()。三角形,矩形和圆形是该接口的三个实现。每个具体的实现都有自己的绘制过程。

Shape shape;

shape = new Triangle();
shape.draw();

shape = new Rectangle();
shape.draw();

shape = new Circle();
shape.draw();

在这里,首先,创建Shape Interface(或Class)的引用。当所有其他三个类都实现(或扩展)它时,shape对象可以引用它们中的任何一个,即,它可以采用任何形式的TriangleRectangle或Circle。以及将使用在运行时确定的绘图过程,具体取决于当时Shape所采用的形式,该形式使用Java中的方法重写行为。

界面 接口是Java开发中广泛使用的Java的另一个关键功能。在访谈中,关于接口的讨论通常以一个简单的问题开始:“什么是接口?”

几乎每个候选人都给出的答案是:“接口是一个只有方法主体但没有实现的类。任何实现接口的类都必须定义或实现自己的方法。”

如果您是经验丰富的Java程序员并且在程序中使用了Interfaces,则此答案仅部分正确。

收到上述答案后,我要问的下一个问题是:“接口的用途是什么?使用接口会带来什么好处?如果没有接口,我们将面临哪些不利条件? ”

在这里,最常见的答案是,当特定功能的行为因对象而异时,则使用接口创建超类,并创建扩展超类的不同子类,并且每个子类都实现其行为。 。并且以上述(形状,三角形,矩形和圆形)或(动物,狗,大象)情况为例。其中Shape或Animal是实现某些接口的超类,而子类则扩展了该超类并实现了特定的行为。

许多候选人提供的另一种用法是使用Java中的Interfaces实现多重继承,否则是不可能的。

以上两个答案都是正确的。但是事实是,第一种情况甚至可以在没有接口的情况下完成,也可以仅通过创建一个超类并通过不同的子类对该类进行扩展来实现。我面试的大多数候选人都停留在这一点上。即使我们无需实现接口也可以做到这一点,为什么还要使用它呢?

如果我们遵循Oracle文档,则在Interfaces的介绍中将显示:

“在软件工程中有很多情况,对于不同的程序员群体来说,重要的是要达成一个“合同”,其中阐明了他们的软件是如何交互的。每个团队都应该能够编写自己的代码,而不必知道彼此之间的交互方式。组的代码是书面的。通常来说, 接口 就是这样的契约。” 让我们一一讨论这些观点。

基本上,接口是开发人员在实施接口时必须遵循的合同。它指出,当您实现某些东西时,必须提供给定的功能集,否则您将不完整。在这里,不完整意味着该类不是完整的类(例如,抽象类)。

这是一个例子:

public Interface Shape {
2
void draw();
3
}

形状是只有一种方法(即)的界面draw()。基本上,这是一个契约,当您实现该接口时,必须实现绘图功能,否则您就不是一个完整的类。因此,对于任何类似TriangleRectangle的类,当我们实现该Interface时,它们都必须实现该 draw()方法。

从程序设计的角度来看,另一个优点是“对接口进行编程,而不是对实现进行编程”的想法 。这意味着在设计代码时,我们应该专注于接口或接口提供的功能,而不是实际的实现。

尽管有时会使用an ArrayList,但我们并不担心List接口所设置的功能是如何由来实现的ArrayList。我们只关心List接口提供的功能,因此在我们的代码中创建了松散的耦合。

List l = new ArrayList();
l.add(xxx)

如果明天我们需要使用LinkedList而不是 ArrayList,我们可以通过更改以下内容轻松地做到这一点:

List l = new LinkedList();

而且我们没有考虑ArrayList程序中使用行为, 因为我们通过接口发布的合同来使用它们。

结论 在学习Java或任何其他编程语言时,我们不仅应关注重要功能,还应关注我们为什么需要它们以及使用它带来的额外好处。如果看不到任何优势,我们应该重新考虑为什么还要使用它。


原文链接:https://codingdict.com/