如果我们可以简单地覆盖超类的方法或使用抽象类,为什么我们应该使用接口?

时间:2015-01-05 10:31:23

标签: java inheritance interface abstract-class method-overriding

我有两个程序,一个使用接口实现,另一个只使用类实现 - 我已经读到使用接口的优点是它可以提供它自己的超类方法的实现,但是可以使用抽象类或方法覆盖来完成。接口有什么用途?
在什么样的层次结构和使用界面的情况下最有利?

INTERFACE

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

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);
    }
}

4 个答案:

答案 0 :(得分:9)

要解释使用接口的原因,您必须首先了解继承问题。它被称为Diamond Problem。简单地说,如果一个类D继承自两个类BC,并且BC都继承自同一个类AA的方法实现D得到了什么?

enter image description here

我们留下的是Java不喜欢的方法歧义!因此,阻止这种情况的方法是确保D 只能只拥有一个超类,因此它可以继承AB或{{ 1}},但绝不会超过一个。这样可以防止出现问题,但是我们失去了多重继承提供的所有好处!

输入界面。这允许我们具有多重继承的特权(将单个类引用为各种不同的类型)并且仍然避免钻石问题,因为实现类提供了该方法。这消除了方法歧义。

这意味着,例如:

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的一个实例时,这非常适合将类彼此解耦,只是它有一个必要的方法子集。

简而言之:您可以实现许多接口,但只能继承一个类

答案 1 :(得分:2)

接口定义合同。比如说:

interface MusicPlayer
{
  public void shuffle();
}

现在每个实现接口的类都可以有自己的算法来实现shuffle方法,它们可以实现。{抽象类与接口类似,其中抽象类定义几个 common 的方法,并以自己的方式让其他方法实现。像

abstract class MusicPlayer
{
  public void turnOff()
  {
     //kill the app
  }

  abstract public void shuffle();
}

使用接口可以实现多个接口,但只能扩展一个类。

答案 2 :(得分:2)

您可以将interface视为社会契约,其中声明实现该接口的所有类都应定义在接口中声明的方法。这在实现它们的所有类之间创建了连续性,如果您希望所有这些类具有相同的行为,那将是非常棒的。由于接口不会声明实现本身,因此将其留给实现它的类。通过这种方式,您可以创建许多具有开始按钮的计算机,这些计算机您可能希望它们具有所有计算机。更好地说需要他们都有,社会契约确保这是事实,因为你必须实现接口的每个方法!这是编译器所必需的。

覆盖其他类中所有方法的class(通过扩展类并在其中实现)并不能真正说明它将始终真正地保留这个承诺。知道班级忠诚的好处已经消失,你掩盖了它背后的逻辑。看看所有方法是否被覆盖都不太清楚,这是不好的做法。为什么不明确逻辑并实际使用界面实现社会契约。

抽象类有点不同,因为它们也实现了方法,正常类可以看到,也可以作为接口使用,因为它们还要求您实现声明但未实现的方法。在java 8中,接口也可以这样做。

答案 3 :(得分:2)

我想说在你的例子中Shape绝对不应该是类,而是接口。您已将区域计算的默认实现提供为x*y,如果大多数形状的情况下此实现不正确。

如果要添加新形状,则将继承具有错误实现的方法。您必须记住检查所有类中的所有方法以验证继承的方法。在界面的情况下,你不能犯这个错误。