我是Java新手,来自C ++背景,我尝试理解实现接口的接口和抽象类的概念。抽象类实现接口时到底发生了什么?这是否像继承一样工作,即所有接口方法都属于abtract类,尽管它们没有在它中实现?或者只有实现的方法属于抽象类?那么实现和扩展之间有什么区别,除了一个用于实现接口而另一个用于继承?
答案 0 :(得分:2)
您可以将abstract
课程视为未完成课程。它就像是实际真实课程的模板。 Interface
主要用于描述属性,例如CanWalk
,IsCloseable
,HasAName
等。
从语言的角度来看,这两个概念之间没有太大的区别,除了你只能从一个类扩展但允许实现多个接口。
在继承链的最后,您将始终拥有非抽象具体类。很明显,你不能使用未完成的类,你需要完成它们。这就是为什么
Animal animal = new Animal();
如果Animal
为abstract
,则无效。我们需要创建已完成的类的实例,例如从Dog
扩展的Animal
。
此时,如果您有已完成(非抽象)类,则需要实现所有抽象方法。无论这些方法来自何处,抽象类或接口,都需要实现它们。
因此,如果您有一个抽象类并使用它实现接口,那么接口方法有两个选项。你要么
假设我们有一个像
这样的界面public interface CanMakeNoise {
void makeNoise();
}
和抽象类
public abstract class Animal implements CanMakeNoise {
public abstract void jump();
...
}
以及具体的扩展类
public class Dog extends Animal {
...
}
由于Dog
不是抽象的,因此需要实现所有方法。也就是说,我们需要jump
和makeNoise
的实现。对于makeNoise
方法,我们有两个选项,Animal
实现它或将其保留为抽象,然后Dog
需要实现它:
// Variant 1
public abstract class Animal implements CanMakeNoise {
public abstract void jump();
@Override
public void makeNoise() {
System.out.println("hello, what's up");
}
}
或
// Variant 2
public abstract class Animal implements CanMakeNoise {
public abstract void jump();
}
public class Dog extends Animal {
@Override
public void makeNoise() {
System.out.println("Wuff wuff");
}
}
当然Dog
需要实施jump
:
public class Dog extends Animal {
@Override
public void jump() {
System.out.println("Boing");
}
...
}
在这种情况下,最好将makeNoise
的实现留给更具体的类,因为Animal
不知道特定动物的声音如何。
扩展示例,如果您有更多具体的类,例如Chihuahua extends Dog
,则可以在makeNoise
中实现Dog
,因为所有的狗都会"Wuff, wuff"
。
答案 1 :(得分:1)
一种方法当然属于实现类。我不会说因为多态性而来自哪里并不重要。在Java中,您不具备多重继承,但您可以实现多个接口,因此这为您提供了有关层次结构的更多选项。
答案 2 :(得分:0)
在Java中,类只能从一个类继承,但可以实现多个接口。
抽象类与接口非常相似。主要区别在于抽象类已经可以定义一些函数,接口不能(注意这在Java9 +中已经改变)。
使用哪一个?那真的取决于你的结构,但javadoc定义了一些例子。
答案 3 :(得分:0)
如果您担心接口的使用,那么它将用于回调,因为Java不支持函数指针。