Мне еще далеко до полного понимания различия между абстрактным классом и интерфейсом. Каждый раз, когда мне кажется, что я понимаю основные понятия, я смотрю на stackexchange и возвращаюсь на два шага назад. Но несколько мыслей по теме и вопросу ОП:
Первый:
Есть два общих объяснения интерфейса:
Интерфейс - это список методов и свойств, которые может реализовать любой класс, и, реализуя интерфейс, класс гарантирует, что эти методы (и их сигнатуры) и эти свойства (и их типы) будут доступны при «взаимодействии» с этим классом или объект этого класса. Интерфейс - это контракт.
Интерфейсы - это абстрактные классы, которые ничего не делают / не могут делать. Они полезны, потому что вы можете реализовать более одного, в отличие от тех средних родительских классов. Например, я мог бы быть объектом класса BananaBread и наследоваться от BaseBread, но это не значит, что я не могу также реализовать интерфейсы IWithNuts и ITastesYummy. Я мог бы даже реализовать интерфейс IDoesTheDishes, потому что я не просто хлеб, понимаешь?
Есть два общих объяснения абстрактного класса:
Знаете, абстрактный класс - это вещь, а не то, что она может сделать. Это похоже на суть, а на самом деле совсем не реально. Погоди, это поможет. Лодка - это абстрактный класс, но сексуальная Playboy Yacht будет подклассом BaseBoat.
Я прочитал книгу об абстрактных классах, и, возможно, вам следует прочитать эту книгу, потому что вы, вероятно, не поняли ее и сделаете это неправильно, если не читали эту книгу.
Кстати, книга Ситерс всегда кажется впечатляющей, даже если я все равно уйду в замешательстве.
Во-вторых:
На SO кто-то задал более простую версию этого вопроса, классическую: «Зачем использовать интерфейсы? Какая разница? Что мне не хватает?» И в одном из ответов в качестве простого примера использовался пилот ВВС. Он не совсем приземлился, но вызвал несколько замечательных комментариев, в одном из которых упоминался интерфейс IFlyable с такими методами, как takeOff, pilotEject и т. Д. И это действительно показалось мне реальным примером того, почему интерфейсы не просто полезны, но важно. Интерфейс делает объект / класс интуитивно понятным или, по крайней мере, дает ощущение, что это так. Интерфейс не для выгоды объекта или данных, но для чего-то, что должно взаимодействовать с этим объектом. Классический Fruit-> Apple-> Fuji или Shape-> Triangle-> Равносторонние примеры наследования являются отличной моделью для таксономического понимания данного объекта на основе его потомков. Он информирует потребителя и процессоров о его общих качествах, поведении, о том, является ли объект группой вещей, будет ли нарушать работу вашей системы, если вы поместите его в неправильное место, или описывает сенсорные данные, соединитель с конкретным хранилищем данных или финансовые данные, необходимые для расчета заработной платы.
Определенный объект Plane может иметь или не иметь метод для экстренной посадки, но я разозлюсь, если предположу, что его аварийная зона, как и любой другой летучий объект, просыпается только в DumbPlane и узнает, что разработчики пошли с quickLand потому что они думали, что это было все то же самое. Точно так же, как я был бы расстроен, если бы у каждого производителя винтов была своя собственная интерпретация правильной силы или если у моего телевизора не было кнопки увеличения громкости над кнопкой уменьшения громкости.
Абстрактные классы - это модель, которая устанавливает, что любой потомственный объект должен квалифицировать как этот класс. Если вы не обладаете всеми качествами утки, то не имеет значения, что у вас реализован интерфейс IQuack, ваш просто странный пингвин. Интерфейсы - это то, что имеет смысл, даже если вы не можете быть уверены ни в чем другом. Джефф Голдблюм и Starbuck оба могли управлять космическими кораблями пришельцев, потому что интерфейс был надежно подобен.
В третьих:
Я согласен с вашим коллегой, потому что иногда вам нужно применять определенные методы с самого начала. Если вы создаете Active Record ORM, ему нужен метод сохранения. Это не до подкласса, который может быть создан. И если интерфейс ICRUD является достаточно переносимым, чтобы не связываться исключительно с одним абстрактным классом, он может быть реализован другими классами, чтобы сделать их надежными и интуитивно понятными для любого, кто уже знаком с любым из классов-потомков этого абстрактного класса.
С другой стороны, ранее был отличный пример того, когда нельзя переходить к привязке интерфейса к абстрактному классу, поскольку не все типы списков будут (или должны) реализовывать интерфейс очереди. Вы сказали, что этот сценарий происходит в половине случаев, а это значит, что вы и ваш коллега оба не правы в половине случаев, и поэтому лучше всего спорить, обсуждать, обдумывать, а если они окажутся правильными, признать и принять связь , Но не становитесь разработчиком, который следует философии, даже если она не самая лучшая для работы.