3

Задумался о таком использовании интерфейсов. Соответственно возник такой вопрос, стоит ли использовать подобный код?

public interface IAnimal
{
    int LegsCount { get; }
}

public interface ICat : IAnimal
{
    string Voice { get; }
}

public abstract class FourLegsAnimal : IAnimal
{
    public int LegsCount => 4;
}

public class DummyCat : FourLegsAnimal, ICat
{
    public string Voice => "I am dummy cat";
}

Код работает, но вот не знаю, имеется ли "запашок" у такого кода

Alex Aparin
  • 1,136
  • а почему IAnimal не может сразу содержать string Voice? – tCode Jan 27 '17 at 09:45
  • 1
    @tCode, как насчет рыб? – Alex Krass Jan 27 '17 at 09:46
  • @AlexKrass есть некоторые виды которые издают звук, вроде как) – tCode Jan 27 '17 at 09:47
  • @AlexKrass, рыбы же не животные? – koks_rs Jan 27 '17 at 09:48
  • 1
    @koks_rs тоже так подумал, но загуглил - написано животные – tCode Jan 27 '17 at 09:49
  • Да, и правда, Домен: Эукариоты, Царство: Животные, Тип: Хордовые, Группа: Рыбы – koks_rs Jan 27 '17 at 09:50
  • Такой код вызывает у меня чувство усложнения структуры и желание его переписать. Мы может дробить сущности очень много и долго, но основная задача стоит в упрощении понимания программы. В данном случае, если наша задача создать просто кошку, то зачем все лишнее? Но если это будет оправдано, то почему нет? – Alex Krass Jan 27 '17 at 10:02
  • Пока ничего ужасного. Ошибка в том, что вы делаете интерфейсы ради интерфейсов, а нужно делать интерфейсы ради упрощения кода. – VladD Jan 27 '17 at 10:05
  • Просто я с подобным паттерном никогда не сталкивался, вот и задумывался как его применить. Правда может иерархия объектов не совсем верная – Alex Aparin Jan 27 '17 at 10:06
  • Просто я пришел из с++, и этот код немного меня смутил. Даже интересно, возможно в с++ так написать. Просто никогда таким способом не пользовался – Alex Aparin Jan 27 '17 at 10:10
  • @koks_rs стоит перенести вопрос на http://biology.stackexchange.com/? –  Jan 27 '17 at 10:17
  • @LmTinyToon, еще почитайте ответы тут Отличия абстрактного класса от интерфейса. Мне кажется тут вопрос больше в том, когда использовать интерфейс и когда абстрактный класс, поскольку они взаимозаменяемы. Переход от интерфейса к абстрактному классу должен быть осознанным и необходимым решением с точки зрения архитектуры. – Alex Krass Jan 27 '17 at 10:21

1 Answers1

3

Мне кажется, говоря об объектной ориентации, не имеет смысла дробить на интерфейсы без необходимости для дизайна программы. Иначе можно получить бесконечное множество интерфейсов: IFourLegs, IHaveWhiskers, IDrinkWater, ILiveOnEarth, IVertebrate, ICarbonBasedLifeForm, IHavingNameInEnglish, IHavingSeparateGenders, и так далее.

Прикиньте сначала вашу иерархию объектов, прикиньте, в какие группы вы будете их группировать и зачем, и только на основе этого стройте ваши интерфейсы.

Возможно, имеет смысл начать вовсе без интерфейсов, написать прототип, и в процессе написания прототипа вдумчиво добавлять нужные интерфейсы (и бить себя по пальцам, чтобы не добавлять ненужные).

VladD
  • 206,799
  • да, думаю в общем случае именно так. Хотя мне кажется такой код симпатичен в следующем случае (возможно изначально я выбрал не совсем верную иерархию) – Alex Aparin Jan 27 '17 at 10:14
  • Что, если модель имеет иерархию, и я хочу что каждый класс реализовывал интерфейс с "read-only" методами. И соответственно использовать эти интерфейсы в gui объектах. Gui объекты тоже будут иметь такую же иерархию. Думаю при таком подходе такой код будет иметь смысл (боюсь что слишком неопределенно обьяснил) – Alex Aparin Jan 27 '17 at 10:15
  • @LmTinyToon: Вооот, вы уже думаете в терминах архитектуры приложения. Это намного лучше. Если интерфейса нужен для приложения, он имеет смысл. – VladD Jan 27 '17 at 11:55