Зависит от ожидаемого использования. В общих чертах я получил два правила, управляющих моей иерархией.
Первый - всегда использовать интерфейс при объявлении аргумента или переменной. Вы решаете это выше, так как вам никогда не придется объявлять переменную Plane. Конечно, это верно только в том случае, если ваш класс самолетов не продлевает контракт, предоставленный IPlane, что будет серьезным «Хммм!»
Второе правило: я представляю только те интерфейсы, которые ожидаю использовать. Так что в приведенном выше примере, если я не ожидал написать одну строку кода, которая будет обрабатывать самолеты и автомобилей
что-то вроде
для каждого автомобиля в транспортных средствах
v.someMethodDefinedByIVehicle ()
Это говорит мне о том, что в моем домене машины и самолеты не одинаковы, и мой код не должен пытаться сделать их такими. То же самое касается IFlyable и IDrivable. IFlyable и IDrivable на самом деле является хорошим примером того, почему вы должны рассматривать только свой собственный домен. Самолет, безусловно, способен управлять автомобилем (в противном случае я не мог бы ездить на такси без посторонней помощи), но только потому, что он управляемый, не означает, что он подходит для дорог, а некоторые автомобили действительно летные, но в большинстве областей это просто.