【发布时间】:2010-09-24 06:57:07
【问题描述】:
接口是一个 100% 的抽象类,因此我们可以使用接口进行高效编程。有没有抽象类比接口更好的情况?
【问题讨论】:
标签: java interface abstract-class
接口是一个 100% 的抽象类,因此我们可以使用接口进行高效编程。有没有抽象类比接口更好的情况?
【问题讨论】:
标签: java interface abstract-class
当您确实打算创建具体类时使用抽象类, 但要确保所有子类中都有一些共同状态 或某些操作的可能通用实现。
接口不能包含任何一个。
【讨论】:
是的,抽象类和接口都有一席之地。
让我们举一个具体的例子。我们将研究如何从抽象的AbstractBankAccount 中创建CheckingAccount 和SavingsAccount,并了解如何使用接口区分这两种类型的帐户。
首先,这是一个抽象类AbstractBankAccount:
abstract class AbstractBankAccount
{
int balance;
public abstract void deposit(int amount);
public abstract void withdraw(int amount);
}
我们的账户余额为balance 和两个必须由子类实现的方法deposit 和withdraw。
正如我们所见,一个抽象类声明了应该如何定义银行账户的结构。正如@Uri 在他的回复中提到的,这个抽象类有一个状态,即balance 字段。这对于接口是不可能的。
现在,让我们将AbstractBankAccount 子类化为CheckingAccount
class CheckingAccount extends AbstractBankAccount
{
public void deposit(int amount)
{
balance += amount;
}
public void withdraw(int amount)
{
balance -= amount;
}
}
在这个子类CheckingAccount 中,我们实现了两个抽象类——这里没什么有趣的。
现在,我们如何实现SavingsAccount?它与CheckingAccount 的不同之处在于它会引起兴趣。使用deposit 方法可以增加利息,但话又说回来,并不是客户自己存入利息。因此,如果我们有另一种将钱存入帐户的方法,专门用于利息,例如accrueInterest 方法,可能会更清楚。
我们可以直接实现SavingsAccount中的方法,但是将来可能会有更多可以产生利息的银行账户类型,所以我们可能想做一个InterestBearing接口,它有accrueInterest方法:
interface InterestBearing
{
public void accrueInterest(int amount);
}
所以,我们现在可以通过实现InterestBearing 接口来创建一个可以引起兴趣的SavingsAccount 类:
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;
}
}
现在,如果我们要创建另一种类型的帐户,比如PremiumSavingsAccount,我们可以创建AbstractBankAccount 的子类并实现InterestBearing 接口来创建另一个计息帐户。
InterestBearing 接口可以看作是为不同的类添加了一个共同的特性。当支票账户没有产生任何利息时,如果有一个功能来处理支票账户的利息,那就没有意义了。
因此,确实存在抽象类和接口在一种情况下共存和协同工作的地方。
【讨论】:
Abstract class v/s interface 是一个让 Java 新手和想要深入研究的人产生很多好奇心/兴趣/困惑的话题。
This article 提供了有关该主题的详细说明。
【讨论】:
您可能更喜欢无实现的抽象类而不是接口的原因有几个:
但另一方面,interface Java 关键字允许更清晰的源代码。
【讨论】:
一般来说,接口描述了您的代码应使用的公共 API,而抽象基类最好作为实现细节保留,其中可以保留通用代码或状态,以减少任何实现类中的重复。
通过在您的 API 中使用接口,人们(包括您)可以更轻松地针对您的类编写测试代码,因为您可以使用不依赖任何外部资源的测试类,或者在现实生活中难以模拟的明显类型的不良但难以模拟的行为。
因此 java 提供 List 接口和 AbstractList 抽象基类以“最小化实现”接口所需的工作量......
【讨论】: