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?
问题:
回答1:
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.
回答2:
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.
回答3:
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.
回答4:
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.
回答5:
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...