2008-11-27 63 views

回答

20

抽象类是用来当你打算创建一个具体类, 但要确保有在所有子类 一些常见的状态或对某些操作可能共同实施

接口不能包含任何一个。

+0

即使定义了抽象类,我也会继续定义接口。它使你的代码更友善,并且更少地耦合到特定的实现。 – tvanfosson 2008-11-27 04:58:44

+0

是的,当然,我同意100%。在我的代码中,我通常将接口界定为接口(听起来很愚蠢),并使用抽象类作为标准实现和状态的基础。 – Uri 2008-11-27 05:09:22

+0

你说:“并且使用抽象类作为标准实现的基础和状态 你可能的意思是: ”并且使用抽象类作为“普通实现”的基础和状态“ – Shaw 2008-11-27 06:36:41

4

抽象类v/s接口是一个话题,对于任何新来的Java人都会产生很多好奇心/兴趣/困惑,并想深入挖掘。

This article提供了关于该主题的详细解释。

8

是的,有抽象类和接口的地方。

让我们来举一个具体的例子。我们将研究如何从摘要AbstractBankAccount制作CheckingAccountSavingsAccount,并了解我们如何使用界面区分这两种类型的帐户。

要开始了,这里是一个抽象类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?它不同于CheckingAccount,因为它会获得利益。通过使用deposit方法可以增加兴趣,但是再一次,它不像顾客自己放置兴趣。因此,如果我们有另一种向账户中添加资金的手段,特别是为了利息,比如说,可以更清楚地说明一种方法。

我们可以直接实现方法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; 
    } 
} 

,如果我们想使anothe r类型的账户,例如PremiumSavingsAccount,我们可以制作AbstractBankAccount的子类并实现InterestBearing接口以创建另一个有息账户。

InterestBearing接口可以看作是将一个共同特征添加到不同的类。在没有任何利息的情况下,拥有一个功能来处理支票账户中的利息是没有意义的。

所以,的确是有两个抽象类和接口共存,并且在一种情况下一起工作的地方。

0

在一般情况下,接口描述,你的代码应该使用公共API,而抽象基类最好保存为一个实现细节,可以保留常见的代码或状态,以减少任何实现类中的重复。

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

所以Java提供了List接口,而AbstractList的抽象基类,以“最大限度地减少实现所需的努力”的界面...

2

有几个原因,你可能更喜欢无实现的抽象类通过接口:

  • 某些不可能的强制转换和instanceof操作可以在编译时捕获。
  • 您可以选择在更高版本中添加具体方法。
  • 许多年前曾经有一个显着的性能优势。
  • 从一个不起眼的高度安全的角度看,你不能让一个已经存在的类创建预先存在的类的子类和抽象类来实现的方法。

但在另一方面,该接口的Java关键字允许更清洁源。