Подтвердить что ты не робот

Разница между чисто абстрактным классом и интерфейсом

У меня была дискуссия с коллегой, который настаивал на том, что в таких языках, как Java и С#, никогда не будет причин использовать базовый класс Pure Abstract, поскольку это просто означает, что вы не можете обойти отсутствие множественного наследования.

Я чувствую, что он ошибается в этом, так как я всегда думал, что если вещь является существительным, то это объект, и если это глагол, то это интерфейс.

Например, если бы я хотел определить тип Bird, где я хотел бы применить метод fly без его реализации, тогда я бы сделал это чистым абстрактным классом.

Если бы я хотел определить тип Flies, я бы сделал его интерфейсом с методом fly.

Bird может реализовать Flies.

Я не прав?

EDIT:

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

Если бы Bird был интерфейсом, это изменение было бы просто кошмаром, так как я не могу знать, реализуют ли вещи, которые наследуют какой-либо другой базовый класс, мой интерфейс Bird, поэтому я не могу просто реорганизовать свои проблемы.

4b9b3361

Ответ 1

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

import java.util.ArrayList;
import java.util.List;


public abstract class AbstractPure implements ISomeInterface {
    public static final List<String> days = new ArrayList<String>();
    static{
        days.add("Monday");
        days.add("Tuesday");
        days.add("Wednesday");      
        days.add("Thursday");   
        days.add("Friday"); 
        days.add("Saturday");   
        days.add("Sunday"); 
    }
}

Ответ 2

Я могу подумать, по крайней мере, о одной веской причине: вы можете расширить абстрактные классы позже, не нарушая обратной совместимости: предположим, что класс/интерфейс

abstract class/interface Foo {
    void foo();
}

Если мы используем интерфейс, мы теперь точно знаем, что нет никакого способа добавить дополнительные функции для Foo. Это может привести к таким вещам, как interface Foo2 implements Foo.

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

Обратите внимание, что Java8 позволит Interfaces делать в основном одно и то же - это будет полезно для библиотек, которые хотят обновить свои библиотеки, чтобы использовать lambdas, не обязательно нарушая совместимость с миллионами уже написанных кода.

Ответ 3

Я занимался поиском чистых абстрактных классов (прошло некоторое время с тех пор, как я в последний раз использовал С++), и единственным вариантом использования, который я мог найти для них, было определение интерфейсов на С++ (у которых нет интерфейсов).

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

Тем не менее, я никогда не сталкивался с необходимостью чистого абстрактного класса в С#, поэтому это может быть гипотетической проблемой.

Ответ 4

Я бы сказал, что оба интерфейса и классы определяют объекты. Как вы сами говорили, глаголы идут на методы - они являются свойствами этих объектов. В вашем примере fly я объявлю интерфейс FlyingCreature и определим в нем метод fly (таким образом, у вас есть такие интерфейсы, как Comparable и Serializable not Serialize и Compare). У вас есть метод compareTo), Также о вашем другом примере - птица: если у вас нет логики для птицы, вы объявляете ее как интерфейс.

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

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

Ответ 5

Скажем, у вас есть система плагинов с несколькими типами плагинов, каждая из которых реализует другой интерфейс.

Теперь давайте также скажем, что вы используете отражение, чтобы найти эти классы плагинов во время выполнения.

Поскольку они являются интерфейсами, один плагин может быть несколькими типами плагинов.

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

Таким образом, существует разница между чистыми абстрактными классами и интерфейсами. Это не тот, который вам нужно использовать, но не есть ++, рекурсия или даже объекты.

Ответ 6

Я кое-что прочитал недавно. В основном он сказал, что если элементы связаны вместе, то используйте абстрактный класс. Если он описывает свойства чего-то, то используйте интерфейс.

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

Если вам просто нужно что-то вроде "флаера", тогда вы сделаете этот интерфейс, потому что птицы и самолеты и другие вещи могут реализовать интерфейс, но его единственное свойство, которое у них есть.

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