В некоторых рекомендациях указано, что вы должны использовать интерфейс, если хотите определить контракт для класса, где наследование не ясно (IDomesticated) и наследование, когда класс является расширением другого (Cat : Mammal, Snake : Reptile), бывают случаи, когда (на мой взгляд) эти рекомендации входят в серое пространство.
Например, скажем, моя реализация была Cat : Pet. Pet - абстрактный класс. Должно ли быть расширено до Cat : Mammal, IDomesticated, где Mammal является абстрактным классом, а IDomesticated является интерфейсом? Или я в конфликте с KISS/YAGNI (хотя я не уверен, будет ли в будущем класс Wolf, который не сможет наследовать от Pet)?
Переходя от метафорических Cat и Pet s, скажем, у меня есть некоторые классы, которые представляют источники для входящих данных. Все они должны каким-то образом реализовать ту же базу. Я мог бы реализовать некоторый общий код в абстрактном классе Source и наследовать его. Я мог бы просто создать интерфейс ISource (который мне кажется более "правильным" ) и повторно реализовать общий код в каждом классе (который менее интуитивно понятен). Наконец, я мог "взять пирог и съесть его", сделав как абстрактный класс, так и интерфейс. Что лучше?
В этих двух случаях возникают точки для использования только абстрактного класса, только интерфейса и использования как абстрактного класса, так и интерфейса. Являются ли эти все действительные выборы или существуют "правила", когда их нужно использовать над другим?
Я хотел бы пояснить, что "используя как абстрактный класс, так и интерфейс", который включает случай, когда они по существу представляют одно и то же (Source и ISource оба имеют одинаковые элементы), но класс добавляет общую функциональность, в то время как интерфейс указывает контракт.
Также стоит отметить, что этот вопрос в основном относится к языкам, которые не поддерживают множественное наследование (например,.NET и Java).