需要抽象类和接口吗?

发布于 2024-07-09 15:26:27 字数 54 浏览 6 评论 0原文

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

An interface is a 100% abstract class, so we can use an interface for efficient programming. Is there any situation where an abstract class is better than an interface?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

怎樣才叫好 2024-07-16 15:26:27

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

接口不能包含其中任何一个。

Abstract classes are used when you do intend to create a concrete class,
but want to make sure that there is some common state in all the subclasses
or a possible common implementation for some operations.

Interfaces cannot contain either.

木槿暧夏七纪年 2024-07-16 15:26:27

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

让我们来看一个具体的例子。 我们将研究如何从抽象的 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方法来增加利息,但话又说回来,这并不是客户自己存入利息。 因此,如果我们有另一种向账户添加资金的方法,特别是利息,例如,accrueInterest 方法,情况可能会更清楚。

我们可以直接在 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;
    }
}

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

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

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

Yes, there is a place for both abstract classes and interfaces.

Let's go with a concrete example. We'll look into how to make a CheckingAccount and SavingsAccount from an abstract AbstractBankAccount and see how we can use an interface differentiate the two types of accounts.

To start off, here's an abstract class AbstractBankAccount:

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

We have the account balance as balance and two methods deposit and withdraw that must be implemented by the subclasses.

As we can see, an abstract class declares the structure of how bank accounts should be defined. As @Uri mentions in his response, there is a state to this abstract class, which is the balance field. This would not be possible with an interface.

Now, let's subclass AbstractBankAccount to make a CheckingAccount

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

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

In this subclass CheckingAccount, we implemented the two abstract classes -- nothing too interesting here.

Now, how could we implement SavingsAccount? It is different from a CheckingAccount in that it will gain interest. The interest could be increased by using the deposit method, but then again, it's not as if the customer is depositing the interest him/herself. Therefore, it might be more clearer if we had another means of adding money into an account, specifically for interest, say, an accrueInterest method.

We could directly implement the method in SavingsAccount, but we may have more bank account types that can accrue interest in the future, so we may want to make an InterestBearing interface that has the accrueInterest method:

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

So, we now can make an SavingsAccount class that can gain interest by implementing the InterestBearing interface:

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;
    }
}

Now, if we want to make another type of account, say a PremiumSavingsAccount, we can make a subclass of the AbstractBankAccount and implement the InterestBearing interface to make another interest-bearing account.

The InterestBearing interface can be seen as adding a common feature to different classes. It would have not have made sense to have a feature to deal with interest in a checking account when it doesn't accrue any interest.

So, there are indeed places for both abstract classes and interfaces to coexist and work together in one situation.

无声静候 2024-07-16 15:26:27

抽象类与接口是一个让任何刚接触 Java 并想要深入挖掘的人产生很多好奇/兴趣/困惑的主题。

这篇文章提供了详细的解释关于这个话题。

Abstract class v/s interface is one topic that generates lot of curiosity/interest/confusion for anyone new to Java and wants to dig deeper.

This article provides a detailed explanation on the topic.

靖瑶 2024-07-16 15:26:27

您可能更喜欢无实现的抽象类而不是接口,原因如下:

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

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

There a couple of reasons why you might prefer an implementation-free abstract class over an interface:

  • Certain impossible casts and instanceof operations can be caught at compile time.
  • You do have the option of adding concrete methods in a later version.
  • There used to be a significant performance benefit many years ago.
  • From a highly obscure security perspective, you can't get a pre-existing class to implement the methods by creating a subclass of the pre-existing class and the abstract class.

But on the other hand, the interface Java keyword allows cleaner source.

疑心病 2024-07-16 15:26:27

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

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

所以java提供了List接口,以及AbstractList抽象基类来“最小化实现”接口所需的工作......

In general, interfaces describe the public API that your code should use, whereas abstract base classes are best kept as an implementation detail, where common code or state can be kept, to reduce duplication in any implementing classes.

By using interfaces in your API, it becomes easier for people (including you) to write test code against your classes, since you can use test classes that, for example, don't depend on any external resources, or which exhibit explicit kinds of bad-but-difficult-to-simulate-in-real-life behaviour.

So java provides the List interface, and the AbstractList abstract base class to "minimize the effort needed to implement" the interface...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文