15

接口是一个 100% 的抽象类,因此我们可以使用接口进行高效编程。是否存在抽象类比接口更好的情况?

4

5 回答 5

21

当您确实打算创建一个具体类时使用抽象类,但要确保所有子类中有一些共同的状态或某些操作的可能的共同实现

接口不能包含任何一个。

于 2008-11-27T04:47:23.483 回答
9

是的,抽象类和接口都有一席之地。

让我们来看一个具体的例子。我们将研究如何从抽象中创建一个CheckingAccount和看看我们如何使用一个接口来区分这两种类型的帐户。SavingsAccountAbstractBankAccount

首先,这是一个抽象类AbstractBankAccount

abstract class AbstractBankAccount
{
    int balance;
    public abstract void deposit(int amount);
    public abstract void withdraw(int amount);
}

我们有帐户余额balance和两个方法depositwithdraw必须由子类实现。

正如我们所见,一个抽象类声明了应该如何定义银行账户的结构。正如@Uri 在他的回复中提到的那样,这个抽象类有一个状态,即balance字段。这对于接口是不可能的。

现在,让我们AbstractBankAccount创建一个子类CheckingAccount

class CheckingAccount extends AbstractBankAccount
{
    public void deposit(int amount)
    {
        balance += amount;
    }

    public void withdraw(int amount)
    {
        balance -= amount;
    }
}

在这个子类CheckingAccount中,我们实现了两个抽象类——这里没什么有趣的。

现在,我们如何实施SavingsAccount?它与 a 的不同之处CheckingAccount在于它会获得兴趣。使用该方法可以增加利息deposit,但话又说回来,并不是客户自己存入利息。因此,如果我们有另一种将钱存入账户的方法,特别是为了利息,比如一种accrueInterest方法,可能会更清楚。

我们可以直接实现 in 中的方法SavingsAccount,但是将来可能会有更多可以产生利息的银行账户类型,所以我们可能想要制作一个InterestBearing具有该accrueInterest方法的接口:

interface InterestBearing
{
    public void accrueInterest(int amount);
}

所以,我们现在可以SavingsAccount通过实现InterestBearing接口来创建一个可以引起兴趣的类:

class SavingsAccount extends AbstractBankAccount implements InterestBearing
{
    public void deposit(int amount)
    {
        balance += amount;
    }

    public void withdraw(int amount)
    {
        balance -= amount;
    }

    public void accrueInterest(int amount)
    {
        balance += amount;
    }
}

现在,如果我们想创建另一种类型的账户,比如 a PremiumSavingsAccount,我们可以创建一个 的子类AbstractBankAccount并实现InterestBearing接口来创建另一个计息账户。

InterestBearing接口可以看作是为不同的类添加了一个共同的特性。当支票账户不产生任何利息时,拥有处理支票账户利息的功能是没有意义的。

因此,确实存在抽象类和接口在一种情况下共存和协同工作的地方。

于 2008-11-27T06:20:55.697 回答
5

抽象类 v/s 接口是一个让 Java 新手和想要深入挖掘的人产生很多好奇心/兴趣/困惑的话题。

本文提供了有关该主题的详细说明。

于 2008-11-27T05:31:35.733 回答
2

您可能更喜欢无实现的抽象类而不是接口的原因有几个:

  • 某些不可能的强制转换和 instanceof 操作可以在编译时被捕获。
  • 您确实可以选择在以后的版本中添加具体方法。
  • 多年前曾经有显着的性能优势。
  • 从高度模糊的安全角度来看,您无法通过创建预先存在的类和抽象类的子类来获得预先存在的类来实现方法。

但另一方面,interface Java 关键字允许更清晰的源代码。

于 2008-11-27T14:05:23.590 回答
0

一般来说,接口描述了你的代码应该使用的公共 API,而抽象基类最好作为实现细节保留,可以保留公共代码或状态,以减少任何实现类中的重复。

通过在您的 API 中使用接口,人们(包括您)可以更轻松地针对您的类编写测试代码,因为您可以使用不依赖于任何外部资源或表现出显式类型的测试类。糟糕但难以模拟现实生活中的行为。

所以java提供了List接口和AbstractList抽象基类来“最小化实现”接口的工作量……

于 2008-11-27T11:37:11.797 回答