需要抽象类和接口吗?

2022-09-03 09:34:44

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


答案 1

当您打算创建一个具体类,但希望确保所有子类中都有一些公共状态或某些操作可能存在的通用实现时,将使用抽象类。

接口也不能包含。


答案 2

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

让我们举一个具体的例子。我们将研究如何从摘要中制作和,并了解如何使用接口区分两种类型的帐户。CheckingAccountSavingsAccountAbstractBankAccount

首先,这里有一个抽象类:AbstractBankAccount

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

我们有账户余额和两种方法,必须由子类实现。balancedepositwithdraw

正如我们所看到的,抽象类声明了应如何定义银行帐户的结构。正如@Uri在他的回应中提到的,这个抽象类有一种状态,即场。使用接口无法做到这一点。balance

现在,让我们子类来制作一个AbstractBankAccountCheckingAccount

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

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

在这个子类中,我们实现了两个抽象类 -- 这里没什么好玩的。CheckingAccount

现在,我们如何实施?它与 a 的不同之处在于,它将获得兴趣。通过使用这种方法可以增加利息,但话又说回来,这并不是说客户自己存入利息。因此,如果我们有另一种将资金添加到帐户中的方法,特别是对于利息,例如一种方法,可能会更清楚。SavingsAccountCheckingAccountdepositaccrueInterest

我们可以在 中直接实现该方法,但是将来我们可能会有更多的银行帐户类型可以累积利息,因此我们可能希望创建一个具有以下方法的接口:SavingsAccountInterestBearingaccrueInterest

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

因此,我们现在可以通过实现接口来创建一个可以获得兴趣的类:SavingsAccountInterestBearing

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 ,我们可以创建一个子类,并实现接口来创建另一个有息帐户。PremiumSavingsAccountAbstractBankAccountInterestBearing

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

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