Нужен абстрактный класс и интерфейс? - PullRequest
14 голосов
/ 27 ноября 2008

Интерфейс - это 100% абстрактный класс, поэтому мы можем использовать интерфейс для эффективного программирования. Есть ли ситуации, когда абстрактный класс лучше интерфейса?

Ответы [ 5 ]

20 голосов
/ 27 ноября 2008

Абстрактные классы используются, когда вы собираетесь создать конкретный класс, но хочу убедиться, что во всех подклассах есть общее состояние или возможная общая реализация для некоторых операций.

Интерфейсы не могут содержать либо.

8 голосов
/ 27 ноября 2008

Да, есть место и для абстрактных классов, и для интерфейсов.

Пойдем с конкретным примером. Мы рассмотрим, как сделать CheckingAccount и SavingsAccount из абстрактного AbstractBankAccount и увидим, как мы можем использовать интерфейс, различающий два типа учетных записей.

Для начала вот абстрактный класс 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);
}

Итак, теперь мы можем создать класс 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 можно увидеть как , добавляющий общую функцию к различным классам. Не имело бы смысла иметь возможность работать с процентами по текущему счету, когда на них не начисляются проценты.

Таким образом, действительно есть места, где абстрактные классы и интерфейсы могут сосуществовать и работать вместе в одной ситуации.

4 голосов
/ 27 ноября 2008

Абстрактный класс v / s интерфейс - это тема, которая вызывает любопытство / интерес / растерянность для тех, кто плохо знаком с Java и хочет копать глубже.

В этой статье приводится подробное объяснение темы.

2 голосов
/ 27 ноября 2008

Есть несколько причин, по которым вы можете предпочесть абстрактный интерфейс, не требующий реализации, а не интерфейс:

  • Некоторые невозможные приведения и операции instanceof могут быть обнаружены во время компиляции.
  • У вас есть возможность добавить конкретные методы в более позднюю версию.
  • Раньше много лет назад было значительное преимущество в производительности.
  • С очень неясной точки зрения безопасности вы не можете получить существующий класс для реализации методов, создав подкласс существующего класса и абстрактного класса.

Но, с другой стороны, ключевое слово Java интерфейса допускает более чистый источник.

0 голосов
/ 27 ноября 2008

В общем, интерфейсы описывают общедоступный API, который должен использовать ваш код, тогда как абстрактные базовые классы лучше всего хранить как подробности реализации, где можно сохранить общий код или состояние, чтобы уменьшить дублирование в любых реализующих классах.

Используя интерфейсы в вашем API, людям (включая вас) становится легче писать тестовый код для ваших классов, поскольку вы можете использовать тестовые классы, которые, например, не зависят от каких-либо внешних ресурсов или которые демонстрируют явные виды плохого, но сложного для моделирования поведения в реальной жизни.

Итак, java предоставляет интерфейс List и абстрактный базовый класс AbstractList для «минимизации усилий, необходимых для реализации» интерфейса ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...