Java 向学生解释接口
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3355408/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Explaining Interfaces to Students
提问by Andy
For a few years I was a teaching assistant for an introduction to programming module - Java for first year undergraduates.
几年来,我担任了编程模块介绍的助教 - 面向一年级本科生的 Java。
Mostly it went well and we managed to get object-oriented programming across to the students quite well, but one thing that students rarely saw the point of was interfaces.
大部分情况下,它进展顺利,我们设法将面向对象的编程很好地传达给了学生,但学生很少注意到的一件事是接口。
Pretty much any explanation we gave either came across as too contrived to be useful for learning, or too far removed from their position as beginners. The reaction we tended to get was "I... see," translated as "I don't understand and they don't sound useful".
我们给出的几乎所有解释要么过于人为而对学习没有用,要么与他们作为初学者的立场相去甚远。我们往往得到的反应是“我……明白了”,翻译为“我不明白,听起来也没有用”。
Anyone here have a way of successfully teaching students about interfaces? I'm not a teaching assistant any more, but it's always nagged at me.
这里有没有人有办法成功地教学生有关界面的知识?我不再是助教了,但它总是对我唠叨。
采纳答案by Ian Dallas
If you are trying to explain it to beginners I would stick with the idea that interfaces can promote code reuse and modularity within the code:
如果你想向初学者解释它,我会坚持接口可以促进代码重用和代码模块化的想法:
For example lets say we are going to paint some objects:
例如,假设我们要绘制一些对象:
public class Painter {
private List<Paintable> paintableObjects;
public Painter(){
paintableObjects = new ArrayList<Paintable>();
}
public void paintAllObjects(){
for(Paintable paintable : paintableObjects){
paintable.paint();
}
}
}
public interface Paintable {
public void paint();
}
Now you could explain to the students that without Paintable interface the Painter object would need to have methods to paint certain types of objects, like a method called paintFences()
and paintRocks()
and we would need to have a new Collection
for each type of objects we want the painter to be able to paint.
现在你可以向学生解释,如果没有 Paintable 接口,Painter 对象需要有方法来绘制某些类型的对象,比如一个被调用的方法paintFences()
,paintRocks()
并且我们需要为Collection
我们希望画家成为的每种类型的对象都有一个新的能够画画。
But thankfully we have interfaces which make painting objects a breeze and how objects are painted is left entirely up to classes that implement the Paintable interface.
但值得庆幸的是,我们有接口可以让绘制对象变得轻而易举,并且对象如何绘制完全取决于实现 Paintable 接口的类。
EDIT
编辑
Another benefit that I forgot to mention is that if you ever need to add new object to paint to your code base, all you need to do is create a new class that implements Paintable and the Painter class never has to change. In this sense the Painter class is never dependent upon the objects it is going to paint, it only needs to be able to paint them.
我忘记提及的另一个好处是,如果您需要向代码库中添加要绘制的新对象,您需要做的就是创建一个实现 Paintable 的新类,而 Painter 类永远不必更改。从这个意义上说,Painter 类从不依赖于它要绘制的对象,它只需要能够绘制它们。
EDIT 2
编辑 2
James Raybould reminded me of a key use of interfaces I forgot to mention: Having an interface between your components, like the Paintable objects and Painter objects, allows you to more easily develop with other people. One developer can work on the Painter objects and another can work on the Paintable objects and all they have to do to function properly together is define a common interface beforehand that they will both use. I know when I've worked on projects with other people in college level projects its really helpful when you are trying to have everyone work on different parts of the project and still have all components come together nicely in the end.
James Raybould 让我想起了我忘记提及的接口的一个关键用途:在组件之间拥有一个接口,例如 Paintable 对象和 Painter 对象,可以让您更轻松地与其他人一起开发。一个开发人员可以在 Painter 对象上工作,另一个可以在 Paintable 对象上工作,他们要一起正常工作所要做的就是事先定义一个他们都将使用的公共接口。我知道当我在大学级别的项目中与其他人一起工作时,当你试图让每个人都在项目的不同部分工作并且最终仍然让所有组件很好地结合在一起时,它真的很有帮助。
回答by Antonio Louro
In this previous question there are some good scenarios that explain the whys behind the use of interfaces.
在上一个问题中,有一些很好的场景可以解释使用接口背后的原因。
回答by corsiKa
"Where classes ARE something, typically interfaces DO something. So I might have a car, but I would never go "carring" but I might go driving... so my Car might implement "drivable" interface."
“类是某种东西,通常接口会做一些事情。所以我可能有一辆车,但我永远不会“开车”,但我可能会开车……所以我的车可能会实现“可驾驶”的接口。”
EDIT:
编辑:
Mark brings up a good point. Interfaces don't do anything at all, but instead define what behaviors happen. And, he also brings up a good point about not wanting to confuse the audience. Not that it's okay to confuse seasoned developers, but it's definitely not a good idea to confuse a brand new student. In light of this, I'm revising my one-liner into a many-liner.
马克提出了一个很好的观点。接口根本不做任何事情,而是定义发生的行为。而且,他还提出了一个不想混淆观众的好观点。并不是说迷惑经验丰富的开发人员可以,但是迷惑一个全新的学生绝对不是一个好主意。鉴于此,我正在将我的单线修改为多线。
"Where classes define existence, interfaces define behavior. Classes define what something is, while interfaces define what something does. So I might have a car, and it has things like an Engine, how much gas it has, what it's historic MPG is, and the like, but I would never go "carring". I might, on the other hand, go Driving... can my Car drive? It can if I give it a Drive method. I can also have "Driveable" interface with a drive method, and leave it up to the car to determine what driving really means. Now, if I only have cars it's not a big deal to have an interface. But what about trucks? If they both are Drivable, I can simply have a List<Drivable
for both of them. Of course, the observant student says "Why can't Car and Truck both simply extend Vehicle, with an abstract Drive method?" Which, actually is a very valid notion. But, what about the Space Shuttle? Very few of the components between Car and Truck apply to the Space Shuttle, so it doesn't seem well suited to extend the Vehicle class. Or what about future cars? We have no idea what they might be like, they might not have chassises, they might just be bubbles of energy that move us around, but we might still call their behavior drive()
."
“类定义存在,接口定义行为。类定义某物是什么,而接口定义某物做什么。所以我可能有一辆汽车,它有诸如引擎之类的东西,它有多少汽油,它的历史 MPG 是什么,之类的,但我永远不会“开车”。另一方面,我可能会去驾驶......我的汽车可以开车吗?如果我给它一个Drive方法就可以。我也可以有“Driveable”接口一种驱动方法,让汽车来确定驾驶的真正含义。现在,如果我只有汽车,那么有一个界面没什么大不了的。但是卡车呢?如果它们都是可驾驶的,我可以简单地拥有一种List<Drivable
对于他们俩。当然,细心的学生会说“为什么 Car 和 Truck 不能都简单地扩展 Vehicle,使用抽象的 Drive 方法?” 这实际上是一个非常有效的概念。但是,航天飞机呢?Car 和 Truck 之间的组件很少适用于 Space Shuttle,因此它似乎不太适合扩展 Vehicle 类。或者未来的汽车呢?我们不知道它们可能是什么样子,它们可能没有底盘,它们可能只是推动我们四处移动的能量气泡,但我们仍可能将它们的行为称为drive()
。”
breathes
呼吸
Now that paragraph/essay is a little verbose, but I could see, with some slides or a chalkboard, being effective for first year students to get their head around (assuming they understand abstract classes first anyway).
现在那个段落/文章有点冗长,但我可以看到,通过一些幻灯片或黑板,对于一年级学生来说是有效的(假设他们首先了解抽象课程)。
回答by Jesus Ramos
Interfaces provide a look at what a class needs to do for instance you can have an Animal interface and lets say that has a method called speak(), well each animal can speak but they all do it differently but this allows you to cast anything that implements animal to animal so you can have a List of animals and make them all speak but use their own implementation. Interfaces are simply wrappers for these kinds of things.
接口提供了一个类需要做什么的例子,例如你可以有一个 Animal 接口,让我们说它有一个叫做 speak() 的方法,好吧,每个动物都可以说话,但它们都以不同的方式说话,但这允许你投射任何实现动物到动物,所以你可以有一个动物列表,让它们都说话,但使用它们自己的实现。接口只是这些东西的包装器。
回答by BalusC
Do you teach JDBC as well? Take it as an example. It's an excellent real world example of how powerful interfaces are. In JDBC you're writing code against an API which exist of almost only interfaces. The JDBC driver is the concrete implementation. You can easily reuse the JDBC code on many DB's without rewriting the code. You just have to switch the JDBC driver implementation JAR file and driver class name to get it to work on another DB.
你也教JDBC吗?以它为例。这是一个很好的现实世界例子,展示了界面的强大。在 JDBC 中,您正在针对几乎只存在接口的 API 编写代码。JDBC 驱动程序是具体的实现。您可以轻松地在许多 DB 上重用 JDBC 代码,而无需重写代码。您只需要切换 JDBC 驱动程序实现 JAR 文件和驱动程序类名即可使其在另一个数据库上工作。
At least, using interfaces offers you the possibility to change from the concrete implementation (the code logic which is responsible for the behaviour) at some way/point without rewriting the whole code. Try to use real world examples when explaining things. It would make more sense.
至少,使用接口为您提供了在不重写整个代码的情况下以某种方式/点更改具体实现(负责行为的代码逻辑)的可能性。在解释事物时尝试使用真实世界的例子。这会更有意义。
回答by YoK
This explains best : (referenced from this tutorial)
这解释得最好:(从本教程中引用)
There are a number of situations in software engineering when it is important for disparate groups of programmers to agree to a "contract" that spells out how their software interacts. Each group should be able to write their code without any knowledge of how the other group's code is written. Generally speaking, interfaces are such contracts. For example, imagine a futuristic society where computer-controlled robotic cars transport passengers through city streets without a human operator. Automobile manufacturers write software (Java, of course) that operates the automobile—stop, start, accelerate, turn left, and so forth. Another industrial group, electronic guidance instrument manufacturers, make computer systems that receive GPS (Global Positioning System) position data and wireless transmission of traffic conditions and use that information to drive the car.
在软件工程中有很多情况,当不同的程序员群体同意一个阐明他们的软件如何交互的“合同”是很重要的。每个组都应该能够在不知道其他组的代码是如何编写的情况下编写他们的代码。一般来说,接口就是这样的契约。例如,想象一个未来社会,计算机控制的机器人汽车在没有人工操作员的情况下在城市街道上运送乘客。汽车制造商编写软件(当然是 Java)来操作汽车——停止、启动、加速、左转等等。另一工业集团,电子制导仪器制造商,
The auto manufacturers must publish an industry-standard interface that spells out in detail what methods can be invoked to make the car move (any car, from any manufacturer). The guidance manufacturers can then write software that invokes the methods described in the interface to command the car. Neither industrial group needs to know how the other group's software is implemented. In fact, each group considers its software highly proprietary and reserves the right to modify it at any time, as long as it continues to adhere to the published interface.
汽车制造商必须发布一个行业标准接口,详细说明可以调用哪些方法来使汽车移动(任何汽车,来自任何制造商)。然后,指导制造商可以编写软件,调用界面中描述的方法来指挥汽车。两个工业集团都不需要知道另一个集团的软件是如何实现的。事实上,每个团体都认为其软件具有高度专有性,并保留随时对其进行修改的权利,只要它继续遵守已发布的界面即可。
More Link: http://download-llnw.oracle.com/javase/tutorial/java/concepts/interface.html
更多链接:http: //download-llnw.oracle.com/javase/tutorial/java/concepts/interface.html
回答by PaiS
Well, recently, I happened to explain this to someone close. The way I explained the question "why Interfaces?", is by taking example of of the USB Port and the USB drives.
嗯,最近,我碰巧向亲近的人解释了这一点。我解释问题“为什么是接口?”的方式是以 USB 端口和 USB 驱动器为例。
The USB port can be considered as a specification, and any USB drive can fit into it, provided they implement the specification. So in this case, the port becomes the Interface and the numerous types of USB sticks available, become the class. Carrying this example ahead, if I were to supply someone an USB drive (class), I would not need to tell them (the calling method) as to what am I passing across. Had the calling method taken a USB drive (class type) as a reference, I would not have been able to pass any but only the USB drive that the port is meant for.
USB 端口可以被视为一种规范,任何 USB 驱动器都可以放入其中,只要它们实现了规范。所以在这种情况下,端口变成了接口,而众多类型的 USB 记忆棒变成了类。继续这个例子,如果我给某人提供一个 USB 驱动器(类),我不需要告诉他们(调用方法)我正在传递什么。如果调用方法采用 USB 驱动器(类类型)作为参考,我将无法传递任何但只能传递端口适用的 USB 驱动器。
To sum it up, Intefaces, help the caller be comptabile with the calling method (in a use-case when the calling method expects an instance of a particular type), no matter what instance you pass across, the caller as well as the callee are sure that it (instance) would fit into the Interface reference (the USB port for analogy).
总而言之,Intefaces 帮助调用者与调用方法兼容(在调用方法需要特定类型实例的用例中),无论您通过哪个实例,调用者以及被调用者确保它(实例)适合接口参考(类比的 USB 端口)。
回答by SargeATM
The real value of interfaces comes with being able to override components in 3rd party APIs or frameworks. I would construct an assignment where the students need to override functionality in a pre-built library that they cannot change (and do not have the source for).
接口的真正价值在于能够覆盖第 3 方 API 或框架中的组件。我会构建一个作业,学生需要覆盖他们无法更改(并且没有源)的预建库中的功能。
To be more concrete, let's say you have a "framework" that generates an HTML page implemented as a Page class. And page.render(stream) generates the html. Let's say that Page takes an instance of the sealedButtonTemplate class. The ButtonTemplate object has its own render method so that in page.render(stream) buttonTemplate.render(label,stream) gets called anywhere there is a button and it produces the html for a submit button. As an example to the students, let's say that we want to replace those submit buttons with links.
更具体地说,假设您有一个“框架”,可以生成一个实现为 Page 类的 HTML 页面。page.render(stream) 生成 html。假设 Page 采用密封的ButtonTemplate 类的实例。ButtonTemplate 对象有它自己的渲染方法,因此在 page.render(stream) buttonTemplate.render(label,stream) 中任何有按钮的地方都会被调用,并为提交按钮生成 html。作为学生的一个例子,假设我们想用链接替换那些提交按钮。
I wouldn't give them much direction other than describing the final output. They will have to pound their heads trying various solutions. "Should we try to parse out the button tags and replace with anchor tags? Can we subclass ButtonTemplate to do what we want? Oh, wait. It's sealed! What were they thinking when they sealed this class!?!"Then after that assignment show a second framework with the ILabeledTemplate interface with the render(label,stream) method.
除了描述最终输出之外,我不会给他们太多指导。他们将不得不绞尽脑汁尝试各种解决方案。“我们应该尝试解析按钮标签并替换为锚标签吗?我们可以将 ButtonTemplate 子类化来做我们想做的事吗?哦,等等。它是密封的!他们密封这个类时在想什么!?!” 然后在该分配之后显示具有 ILabeledTemplate 接口和 render(label,stream) 方法的第二个框架。
回答by Thorbj?rn Ravn Andersen
I usually use "contract" but "promises solemnly to provide" might also help understanding.
我通常使用“合同”,但“郑重承诺”也可能有助于理解。
回答by Hut8
In addition to the other answers, you could try explaining it from a different perspective. The students I'm sure already know about inheritance because it is jammed down the throats of every Java student from probably lecture one. Have they heard about multiple inheritance? Method resolution was seen as a design issue in C++ (and also in Perl and other multiple-inheritance languages) because conceptually it's ambiguous as to exactly what should happen when a method is called in a subclass that is defined in two of its base classes. Are both executed? Which one goes first? Can one be referenced specifically? See also the diamond problem. It's my understanding that this confusion was resolved simply by introducing interfaces, which have no implementation, so there's no ambiguity as to which implementation to use during method resolution.
除了其他答案之外,您还可以尝试从不同的角度进行解释。我相信学生们已经知道继承,因为它可能从第一课开始就被每个 Java 学生堵在喉咙里。他们听说过多重继承吗?方法解析被视为 C++(以及 Perl 和其他多继承语言)中的一个设计问题,因为从概念上讲,当在其两个基类中定义的子类中调用方法时,究竟会发生什么是不明确的。两个都被执行了吗?哪个先走?可以具体参考一下吗?另见钻石问题. 我的理解是,这种混淆只是通过引入没有实现的接口来解决的,因此在方法解析期间使用哪个实现没有歧义。