Когда использовать интерфейсы или абстрактные классы? Когда использовать оба?

Хотя в некоторых рекомендациях говорится, что вы должны использовать интерфейс, если вы хотите определить контракт для класса, в котором наследование неясно (IDomesticated) и наследование, когда класс является продолжением другого (,Cat : MammalSnake : Reptile), бывают случаи, когда (по моему мнению) эти рекомендации попадают в серую зону.

Например, скажем, моя реализация была.Cat : PetPet это абстрактный класс. Должно ли это быть расширено доCat : Mammal, IDomesticated гдеMammal абстрактный класс иIDomesticated такое интерфейс? Или я в конфликте сПОЦЕЛУЙ/YAGNI принципы (хотя яЯ не уверен, будет лиWolf класс в будущем, который не сможет унаследовать отPet)?

Отойдя от метафорическогоCatс иPetс, давайскажем, у меня есть несколько классов, которые представляют источники для входящих данных. Им всем нужно как-то реализовать одну и ту же базу. Я мог бы реализовать некоторый общий код в абстрактномSource класс и наследовать от него. Я также мог бы просто сделатьISource интерфейс (который чувствует больше "право" для меня) и повторно реализовать общий код в каждом классе (который менее интуитивно понятен). Наконец-то я смогесть торт и съесть его делая как абстрактный класс, так и интерфейс. Какие'лучше?

Эти два случая поднимают вопрос об использовании только абстрактного класса, только интерфейса и как абстрактного класса, так и интерфейса. Это все действительные выборы, или есть "правила» когда один должен быть использован поверх другого?

Я хотел бы уточнить этоиспользуя как абстрактный класс, так и интерфейс " это включает в себя случай, когда они по существу представляют собой одно и то жеSource а такжеISource оба имеют одинаковых членов), но класс добавляет общие функциональные возможности, в то время как интерфейс определяет контракт.

Также стоит отметить, что этот вопрос в основном относится к языкам, которые не поддерживают множественное наследование (например, .NET и Java) .I '

Ответы на вопрос(7)

Ваш ответ на вопрос