我确切地知道接口和抽象类之间有什么区别,但为什么接口有用呢?看看这个:
答案 0 :(得分:6)
现在想象一下抽象Point
和Circle
。您如何实现MovablePoint
同时为Movable
和Point
?只有界面可以为您提供,以及它们的用途。
答案 1 :(得分:1)
参见 HERE
- 如果您认为计划使用继承,那么抽象类很好,因为它提供了一个公共基类实现 派生类。
- 如果您希望能够声明非公开成员,那么抽象类也很好。在界面中,所有方法都必须是公共的。
- 如果您认为将来需要添加方法,那么抽象类是更好的选择。因为如果你添加新方法 标题到接口,然后是所有类 实现该接口必须更改以实现新的 方法。这可能会非常麻烦。
- 当您认为API暂时不会改变时,接口是一个不错的选择。
- 当你想拥有类似于多重继承的东西时,接口也很好,因为你可以实现多个接口。
在你的场景中只有你可以指定的接口,如果MovablePoint是Movable和Point。
答案 2 :(得分:0)
想象一下,使用你的图书馆的人想要介绍其他可用的东西,比如 MovableTirangle
。如果他们让这个工具Movable
,它可以完美地与您的图书馆一起使用。
例如,库提供了
void move(Movable m, int horiz, int vert) {
int i;
if (horiz >= 0) {
for (i=0; i < horiz; i++) {
m.moveRight();
}
} else {
for (i=0; i > horiz; i--) {
m.moveLeft();
}
}
if (vert >= 0) {
for (i=0; i < vert; i++) {
m.moveUp();
}
} else {
for (i=0; i > vert; i--) {
m.moveDown();
}
}
}
,可用于所有当前和未来的 Movable
种。
到目前为止,这对于基类也是有效的,因此实际上并不重要。
但是,由于Java不支持多重继承,因此类不能从多个基类继承。但如果需要,可以实现多个接口。
此外,如果你有一个功能界面(你没有,因为你有多个非默认函数),你还可以使用Java的新lambda特性。这是另一件不适用于抽象类的东西。
答案 3 :(得分:0)
是的 - 在这种情况下你可以拥有,但也要考虑更大的图景。当我第一次学习OOP时,我问同样的问题,并且界面让我困惑了很长时间。
如果你想将'可移动'方法添加到不是Point的子类的对象,假设'MovableJPEG'或者其他类似的东西。移动操作的最终结果将是相同的,但您必须重写两个类和不同方法的接口,以处理在与Movable对象交互的类中移动这些功能。
使用接口传递任意数量的类型,仅通过使用相同方法的类似接口,因为它们的实现细节保证相同。
答案 4 :(得分:0)
接口和抽象类都允许程序员编写模块化类。
接口优于抽象类的优点是它不带任何预定义的方法或属性。抽象类可能包含您不希望在类中实现的内容。
第二个优点是java类只能扩展一个类,但只能扩展大量接口。
接口提供了更多的自由,抽象类可以影响类的内部设计。抽象类的一个优点是代码共享,这对于接口来说更加困难。
答案 5 :(得分:0)
答案 6 :(得分:0)
我不会列出使用接口或抽象类之间的所有差异,或者何时使用它们中的每一个,我认为你会在网上找到很多资源,所以只讨论它,例如:{{3 }}
要回答你,是,您只能在示例中使用抽象类,而不必使用界面
但,存在概念差异,未创建接口以公开公共行为,它是可以执行的类的合同< / strong>即可。 虽然抽象类是层次结构的父级,但可以生成具有核心结构并提供默认行为的子级。
从概念上讲,Movable
必须是Interface
,因为它定义了implements Movable
可以做什么的类(可以向上移动,向下移动,移动.. 。)而不是如何这样做(Circle dosn像Rectangle一样移动)。虽然您的MovableCircle
可能是abstract class
,但我们可以定义以下方法:calculateArea()
,getRadius()
,calculateCircumference()
,...这是类的默认行为将继承自MovableWheel
。
答案 7 :(得分:0)
让你试图给一些不相关的类提供类似的属性。然后你可以使用界面。例如 -
<Bounceable>
/ \
Ball Tire
此处Ball
和Tire
(汽车)完全无关。但他们都是Bounceable
。如果您希望两个不相关的类具有相同的属性,则可以使用interface。
接口还有另一个重要用途 - 提供多重继承的风格,但比多重继承更有效(存在常见的Deadly Diamond of Death问题。)。例如,您期望Ball
应该同时为Bouncable
和Serializeable
。 Bouncable
和Serializeable
完全无关。然后你可以在这里使用界面。抽象类需要扩展/继承,并且java
多个inheritance
是不可能的。因此,我们可以通过使用接口为类提供完全不相关的属性。
答案 8 :(得分:0)
这是一个带有Cat和Dog类的代码示例(C#),它使用了interface和absctract类,希望它们能够突出它们之间的差异。
假设1:两只动物都说声音,但这些是不同的声音(需要不同的方法) 假设2:两只动物都可以吃,如果它们不满(这两种动物都需要一种方法)
static void Main(string[] args)
{
IanimalBehavior pluto = new Dog();
IanimalBehavior simba = new Cat();
Program.makeAnimals_say_and_eat(pluto);
Program.makeAnimals_say_and_eat(simba);
Program.makeAnimals_say_and_eat(pluto);
Program.makeAnimals_say_and_eat(simba);
Console.ReadLine();
}
static void makeAnimals_say_and_eat(IanimalBehavior animalObject)
{
Console.WriteLine(animalObject.makeSound());
Console.WriteLine(animalObject.eat());
}
interface IanimalBehavior {
string makeSound();
string eat();
}
class Dog : Animal, IanimalBehavior {
public string makeSound() {
return this.GetType().Name + " says: wuf";
}
}
class Cat : Animal, IanimalBehavior {
public string makeSound()
{
return this.GetType().Name + " says: miauw";
}
}
abstract class Animal {
bool _isFull = false;
public string eat()
{
if (_isFull == false)
{
_isFull = true;
return this.GetType().Name + " is now eating";
}
else
{
return this.GetType().Name + " is now too full to eat!";
}
}
}
请注意,动物被声明为接口类型:
IanimalBehavior pluto = new Dog();
这将确保方法makeAnimals_say_and_eat()可以采用针对两种类型的对象(Cat&amp; Dog)的参数类型,因此所有动物只需要一种方法,这就是我们想要的。
static void makeAnimals_say_and_eat(IanimalBehavior animalObject)
{
Console.WriteLine(animalObject.makeSound());
Console.WriteLine(animalObject.eat());
}
该方法从作为参数传递的任何对象调用.makeSound()和.eat()。编译器很高兴,因为它知道任何IanimalBehavior类型都必须包含这两种方法,因为它在合同中这样说:
interface IanimalBehavior {
string makeSound();
string eat();
}
on .makeSound()返回值取决于类类型,而.eat()对于两个类都相同,因为eat()在所有动物继承的absctract类Animal中声明。
这些指示的输出:
Program.makeAnimals_say_and_eat(pluto);
Program.makeAnimals_say_and_eat(simba);
Program.makeAnimals_say_and_eat(pluto);
Program.makeAnimals_say_and_eat(simba);
是:
Dog says: wuf
Dog is now eating
Cat says: miauw
Cat is now eating
Dog says: wuf
Dog is now too full to eat!
Cat says: miauw
Cat is now too full to eat!
接口类型还为您提供了在单个数组中存储具有相似性质的不同对象(相同的接口实现)的选项,然后您可以迭代这些对象。
IanimalBehavior[] animal_list = { new Dog(), new Cat()};
foreach (IanimalBehavior animal in animal_list)
{
Console.WriteLine(animal.eat());
Console.WriteLine(animal.makeSound());
}