如果我们可以简单地覆盖超类的方法或使用抽象类,为啥还要使用接口? [复制]
Posted
技术标签:
【中文标题】如果我们可以简单地覆盖超类的方法或使用抽象类,为啥还要使用接口? [复制]【英文标题】:Why should we use interface if we can simply override methods of the superclass or use abstract classes? [duplicate]如果我们可以简单地覆盖超类的方法或使用抽象类,为什么还要使用接口? [复制] 【发布时间】:2015-03-02 21:06:17 【问题描述】:我有两个程序,一个使用接口实现,另一个仅使用类实现 - 我读过使用接口的优点是它可以提供它自己的超类方法的实现,但可以使用抽象类或方法覆盖来完成。接口的用途是什么? 在什么样的层次结构和情况下使用接口最有利? 界面
interface Shape
void area(int x, int y);
class Rectangle implements Shape
@Override
public void area(int length, int breadth)
System.out.println(length*breadth);
class Triangle implements Shape
@Override
public void area(int base, int height)
System.out.println(base*height);
public class ShapeUsingInterface
public static void main(String X[])
Rectangle r = new Rectangle();
Triangle t = new Triangle();
r.area(5, 4);
t.area(6, 3);
类
class Shape
void Area(int x, int y)
System.out.println(x*y);
class Rectangle extends Shape
class Triangle extends Shape
@Override
void Area(int base, int height)
System.out.println((0.5)*base*height);
public class CalculateArea
public static void main(String X[])
Rectangle r = new Rectangle();
Triangle t = new Triangle();
r.Area(4, 5);
t.Area(6, 8);
【问题讨论】:
你可以实现多个接口,但只能扩展一个类 嗯,重要的区别在于,接口定义了一个牢不可破的合约。因此,它使实现它的类显式实现该方法。另一方面,一个类并不明确期望您实现这些方法。 【参考方案1】:要解释为什么要使用接口,首先要了解继承的一个问题。它被称为Diamond Problem。简单来说,如果一个类D
继承自两个类B
和C
,而B
和C
都继承自同一个类A
,那么A
中的方法的实现就是@ 987654330@得到?
我们留下的是Java 不喜欢的方法歧义!所以防止这种情况的方法是确保D
只能拥有一个超类,因此它可以继承自A
、B
或C
,但不能超过一。这样可以避免问题,但我们失去了多重继承提供的所有好处!
进入界面。这允许我们拥有多重继承的好处(将单个类引用为各种不同的类型)并且仍然避免菱形问题,因为实现类提供了方法。这消除了方法的歧义。
这意味着,例如:
public abstract class MyClass
public void doSomething();
public class MyConcreteClass extends MyClass
public void doSomething()
// do something
您可以将MyConcreteClass
的实例引用为
MyClass class = new MyConcreteClass();
或
MyConcreteClass class = new MyConcreteClass();
但是,鉴于此实现,别无其他。您不能extend
更多课程,因为您可能会遇到钻石问题,但您可以包含Interface
public class MyConcreteClass extends MyClass implements Serializable
突然间,你可以说..
Seralizable myClass = new MyConcreteClass();
因为myClass
是一个 Serializable
。当一个方法可能不需要知道它是MyConcreteClass
的一个实例时,这对于将类彼此解耦非常有用,只需知道它具有必要的方法子集。
简而言之:你可以实现很多接口,但你只能继承一个类。
【讨论】:
好答案。我还想在您的回答中看到您可以实现多个接口,但只能在此答案的某处将一个类扩展为一行。我希望阅读这篇文章,但没有直接看到。 @Joop 已为您添加。【参考方案2】:接口定义契约。比如说:
interface MusicPlayer
public void shuffle();
现在每个类实现接口可以有自己的算法来实现shuffle
方法,这取决于他们。抽象类类似于接口,其中抽象类定义几个方法是通用,而让其他方法以我们自己的方式实现。喜欢
abstract class MusicPlayer
public void turnOff()
//kill the app
abstract public void shuffle();
使用接口,您可以实现多个接口,但只能扩展一个类。
【讨论】:
【参考方案3】:我会说,在您的示例中,Shape
绝对不应该是类,而是接口。您已将面积计算的默认实现提供为x*y
,但在大多数形状的情况下,此实现不正确。
如果您要添加新形状,您将继承执行不正确的方法。您必须记住检查所有类中的所有方法以验证继承的方法。在接口的情况下你不能犯这个错误。
【讨论】:
【参考方案4】:您可以将interface
s 视为一种社会契约,它规定所有实现接口的类都应定义接口中声明的方法。这在实现它们的所有类之间创建了连续性,如果您希望所有这些类具有相同的行为,那就太棒了。由于接口不声明实现本身,因此将其留给实现它的类。通过这种方式,您可以创建许多具有启动按钮的机器,您可能希望它们都拥有。更好的说法是要求他们都拥有,社会契约确保了这种情况,因为你必须实现接口的每一个方法!这是编译器要求的。
class
覆盖了其他类的所有方法(通过扩展类并在其上实现)并不能真正表示它会始终真正信守承诺。知道班级将忠诚的好处已经消失,并且您掩盖了其背后的逻辑。查看是否所有方法都被覆盖将不太清楚,这是不好的做法。为什么不把你的逻辑说清楚,用一个接口实际实现社会契约。
抽象类有点不同,因为它们也实现了与普通类一样的方法,并且还作为接口工作,因为它们还要求您实现已声明但未实现的方法。在 java 8 接口中也可以做到这一点。
【讨论】:
由于默认实现,对于 java8,此答案不再完全正确。在 Java 8 中,接口也可能包含某些方法实现。以上是关于如果我们可以简单地覆盖超类的方法或使用抽象类,为啥还要使用接口? [复制]的主要内容,如果未能解决你的问题,请参考以下文章