接口的意图与使用抽象方法的抽象类有何不同?

时间:2011-08-26 11:20:34

标签: java interface abstract-class

解释/前导

在Java中,如果使用抽象方法声明抽象类,例如

public abstract class MyAbstractClass {
  private String m_id;

  // default behavior
  public MyAbstractClass() { setId(null); }
  public String getId() { return m_id; }
  public void setId(String id) { m_id = id; }

  // overridenable method
  public void doSomething() { /* does nothing by default */ }

  // to-be-defined behavior
  public abstract void setSomething(Object o);
  public abstract Object getSomething();
}

你可以有效地声明一个具有各种“默认行为”的类(m_id的getter和setter)以及强制这个类是由一个子类实例化的实现“缺失”(抽象)方法,例如

public class MyClass extends MyAbstractClass {
  private Object m_o;

  // implements some actual complex behavior
  public void setSomething(Object o) { m_o = o; }
  public Object getSomething() { return m_o; }
}

甚至可能覆盖超类中的方法。

所以 似乎 带抽象方法的抽象类表现为 ,好像 它是{{1 }},

interface

因为要使用它,它必须最终指向实际对象

问题

几乎似乎在现有public interface IMy { public void setSomething(Object o); public Object getSomething(); } interface - with-abstract-methods(ACWAM)中没有任何意义,因为它们似乎非常类似。

  1. ACWAM似乎abstract class非常相似!我认为本质区别在于 intent
  2. 我知道interface打算提供一种方法,库用户可以与库“交谈”,而不依赖于库的实现。如果interface旨在“向公众展示某些东西”是正确的解释,而ACWAM是供图书馆开发人员“同意”的东西,但具有“额外奖励”提供默认(可覆盖)行为?
  3. 与ACW​​AM同时使用interface是否有意义?
  4. 你能提供一两个简单的例子(指向另一个文件会很好)来说明这两个人的意图(或“好用”)的差异,即interface和ACWAM?

5 个答案:

答案 0 :(得分:5)

接口和抽象类之间的最大区别是:

  • 抽象类强制实现“是一种”关系。您必须子类化抽象类。您永远被绑定到特定的类层次结构
  • 接口强制实现“看起来像”关系。只要它遵循接口,您就可以将任何您喜欢的子类化。这使您可以在任何您喜欢的课程中进行交换。如果出现更好的一个
  • ,这尤其有用

一个好的规则就是API应该始终引用接口。

请注意,JDK中充斥着早期使用接口应该使用的(抽象)类的错误。 Stack是一个很好的例子:Stack 应该是一个接口,但它是一个类。如果你想实现自己的堆栈,你必须子类 java.util.Stack,这是非常规范的 - 你可能不想这样做 - 也许你需要一个超轻量级版本等。

抽象类确实有它们的位置:它们可以提供接口的默认实现。一个很好的例子是java.util.AbstractMap,这是一个java.util.Map接口的骨架实现的类。

答案 1 :(得分:1)

Java不支持多重继承。因此,一个类可以实现许多接口,但它不能从多个基类继承。

答案 2 :(得分:1)

如果有帮助,您可以将Java接口视为契约,将Java抽象类视为模板。

答案 3 :(得分:0)

Abstarct类使用一些/所有抽象方法。 但接口是所有抽象方法。

在所有方法都是abstarct的senarios中,然后选择接口:

interface City
{
   public void pin();
   public void state();
}
任何城市实现的

都必须为这两种抽象方法提供自己的实现。

例如:

class Bangalore implements City
{
   public void pin()
   {
       System.out.println("127351731");
   }
   public void state()
   {
       System.out.println("Karnataka");
   }
}

class Lisbon implements City
{
   public void pin()
   {
       System.out.println("87456964");
   }
   public void state()
   {
       System.out.println("Lisbon");
   }
}

但是举个例子来说:在这样的场景中,某些方法对于扩展此类的类是常见的,但有些方法必须提供不同的实现:

abstract class Animal{
  public abstract void eat();

  public void run()
  {
     System.out.println("I can Run");
  } 

}

让我们说Dog和Cat都扩展了这个抽象类。它们都将从Animal类继承相同的run()。

class Dog extends Animal
{
    public void eat()
    {
       System.out.println("I eat Meat");
    }
}

class cat extends Animal
{
    public void eat()
    {
       System.out.println("I eat only Fish");
    }
}

答案 4 :(得分:0)

如果你必须在只有抽象方法的接口和抽象类之间做出选择,你应该选择接口,因为它为你提供了更多的可能性:你可以有多个接口,但只有一个抽象类。

如果您需要一些常见的行为,您也可以选择接口,因为您可以通过具体类中的组合获得共同行为(并且您可以从多重继承中获益)。