Если я не ошибаюсь, вы не совсем поняли, какой целью является интерфейс по сравнению с типом.
В терминах ООП интерфейсы не имеют реализаций. Типы делают. Таким образом, интерфейс в основном бесполезен, если только этот тип не реализует его. Кроме того, тип может распространять только один тип. Но он может реализовывать множество интерфейсов.
Но что это значит ...
Скажем, у вас есть автомобиль, и пользователя. Очень разные типы, которые вы не сразу думаете, как одно и то же в любом практическом смысле. Некоторые могут сказать: «ну, вы должны создать ICar и IUser». Но на самом деле, это просто не практический способ думать об интерфейсах. Было бы странным, если бы Пользователь реализовал ICar, и/или, похоже, ICar делает то же самое, что и Car. Какая разница с другим программистом, смотрящим на код?
Скажите, что вы хотите, чтобы они оба были (снова просто для этого), «Self Describable», и вы хотите, чтобы они оба предоставили информацию таким же образом. Таким образом, вы бы создать:
ISelfDescribable {
getSelfDescription ();
}
Теперь, вы могли бы сделать это:
Car implements ISelfDescribable {
getSelfDescription (return "I am a car!");
}
User implements ISelfDescribable {
getSelfDescription (return ...some other completely different way of getting the info...);
}
Массив этих объектов будет (думать о том, как еще вы могли бы сделать это без интерфейсов):
Array<ISelfDescribable>
Теперь вы (и любой другой разработчик, смотрящий на код) знают, что любой объект в этом массиве, независимо от конкретного типа, реализует «поведение» ISelfDesribable
. Если вы думаете об этом, нет необходимости НИКОГДА знать, что такое тип, если вы его не реализуете, вы просто заботитесь о поведении. Но вам все равно нужен тип для реализации этого поведения.
Скажите, что однажды вы хотели, чтобы оба этих объекта были «Надежными». Они оба должны иметь метод, "setInsurancePolicy"
. Вы можете создать IInsurable { setInsurancePolicy (policy : Policy) }
и реализовать его в типах. Теперь у вас есть объекты, которые являются как ISelfDescribable
, так и IInsurable
, и вы можете ввести массив этих объектов как один.
Для меня большая лампочка погасла, когда я обнял ее: типы (и иерархии типов) должны быть связаны с конкретными вещами. Интерфейсы должны быть связаны с поведением, которое может использоваться для разных типов. Это еще не все, но, по крайней мере, дает представление о том, почему вы выбираете интерфейс или тип. Они представляют разные вещи с точки зрения программирования, даже если они выглядят одинаково.
(Приложение: такие языки, как Scala, не воспринимают в терминах интерфейсов таким образом. У них есть понятие «поведения», но вы также можете реализовать поведение и переопределить их. Это может быть слишком много академического взрыва для этот конкретный вопрос, но эй, мне нужно убить всех монстров в подземелье, а не только тех, для квеста).