需要抽象类和接口?
接口是100%抽象类,因此我们可以使用接口进行高效编程。 是否存在抽象类优于接口的情况?
当您打算创建具体类时,会使用抽象类,但希望确保所有子类中都存在某种公共状态 ,或者某些操作可能采用常见实现 。
接口也不能包含。
是的,抽象类和接口都有一个位置。
我们来看一个具体的例子吧。 我们将研究如何从抽象的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
子类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
实现该方法,但是我们可能会有更多银行帐户类型可以在将来产生兴趣,因此我们可能想要创建一个具有accrueInterest
方法的InterestBearing
接口:
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
界面可以看作是为不同的类添加一个共同的function 。 如果没有产生任何利息,那么拥有一个处理支票账户利息的function是没有意义的。
因此,在一种情况下,确实存在抽象类和接口共存和协同工作的地方。
抽象类v / s接口是一个主题,它为任何刚接触Java的人提供了许多好奇心/兴趣/困惑,并希望深入挖掘。
本文提供了有关该主题的详细说明。
您可能更喜欢在接口上使用无实现的抽象类,这有几个原因:
- 某些不可能的强制转换和instanceof操作可以在编译时捕获。
- 您可以选择在更高版本中添加具体方法。
- 多年前曾经有过显着的性能优势。
- 从高度模糊的安全角度来看,您无法通过创建预先存在的类和抽象类的子类来获得预先存在的类来实现这些方法。
但另一方面,接口Java关键字允许更清晰的源。
多一个:
有一篇关于Java世界的文章描述了将接口和抽象类一起使用:
查看关于Java World的这篇文章
通常,接口描述您的代码应该使用的公共API,而抽象基类最好保留为实现细节,其中可以保留公共代码或状态,以减少任何实现类中的重复。
通过在API中使用接口,人们(包括您)可以更轻松地针对您的类编写测试代码,因为您可以使用测试类,例如,不依赖于任何外部资源,或者显示明确类型的测试类。现实生活中很难但难以模拟的行为。
所以java提供了List接口,而AbstractList抽象基类则“最小化了实现接口所需的工作量……”