Смесь интерфейса и базового класса, правильный способ реализовать это

У меня есть некоторые пользовательские элементы управления, для которых я хочу указать свойства и методы.

Они наследуются от базового класса, потому что все они имеют такие свойства, как «Foo» и «Bar», и причина, по которой я использовал базовый класс, заключается в том, что мне не нужно вручную реализовывать все эти свойства в каждом производном классе.

Однако я хочу иметь метод, который находится только в производных классах, а не в базовом классе, поскольку базовый класс не знает, как «сделать» метод, поэтому я думаю об использовании для этого интерфейса. Если я помещу его в базовый класс, мне придется определить какое-то тело, чтобы возвращать значение (которое было бы недействительным), и всегда следить за тем, чтобы переопределяющий метод не вызывал базу. метод

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

Дайте мне знать, если вопрос не ясен, это, вероятно, глупый вопрос, но я хочу сделать это правильно.

РЕДАКТИРОВАТЬ: спасибо всем людям с вашими отличными абстрактными предложениями, но это ломает дизайнера. Если бы абстракция не была выбираемой опцией, что бы вы сделали?


person Greg Olmstead    schedule 08.06.2010    source источник
comment
Я решил использовать базовый класс и создать исключение NotImplemented. Вероятно, это не лучший дизайн, но он избавляет меня от необходимости реализовывать множество свойств для каждого отдельного производного класса и должен стать проблемой только в том случае, если кто-то забудет реализовать метод. Если бы я только мог превратить это в ошибку компиляции. Спасибо за все ваши предложения, если у кого-то еще есть что-то полезное, чтобы внести свой вклад, пожалуйста, оставьте комментарий.   -  person Greg Olmstead    schedule 08.06.2010
comment
Вы можете просто потребовать, чтобы компоненты реализовывали определенный интерфейс. Допустим, у вас есть панель, на которую вы добавляете подключаемые компоненты пользовательского интерфейса. Для метода добавления может потребоваться интерфейс подключаемого компонента, например Plug1 : BaseControl, IPluggable {...} void AddComponent(IPluggable componentToAdd) {...}   -  person Scott P    schedule 08.06.2010
comment
Да, это то, что я сделал изначально, но я надеялся избежать реализации как базового класса, так и интерфейса, и необходимости переключаться между ними, чтобы вызывать их членов   -  person Greg Olmstead    schedule 08.06.2010


Ответы (5)


В качестве альтернативы вы можете определить метод как «абстрактный» в базовом классе, что не потребует от класса его реализации. Например:

abstract class A
{
   public abstract void B();
}

Конечно, это также заставит ваш базовый класс быть абстрактным, но похоже, что это отлично сработает для вас.

См. Абстрактные методы в MSDN.

Обновить

Поскольку abstract не подходит для вас из-за проблем с разработчиком, вы можете просто определить метод как часть вашего базового класса и заставить его вызывать NotImplementedException, если он вызывается непосредственно из базового класса:

void DerivMethod()
{
    // Must be implemented by derived class
    throw new NotImplementedException();
}

В противном случае можно использовать interface, особенно если это оставляет неприятный привкус во рту...

person Justin Ethier    schedule 08.06.2010
comment
Вы должны быть осторожны при создании абстрактных пользовательских элементов управления. На самом деле это будет проблематично для дизайнера. Если дизайнеру не нужно изменять производные пользовательские элементы управления, это будет работать нормально. - person Scott P; 08.06.2010
comment
Скотт прав в этом, мне нужно иметь возможность использовать конструктор, а это делает его невозможным. Тем не менее, все остальное в нем прекрасно работает, но именно по этой причине я не использовал абстрактный - person Greg Olmstead; 08.06.2010
comment
Все эти решения работают, однако возникает одна и та же проблема: мне пришлось бы либо реализовать все свойства интерфейса в каждом производном классе, либо выдать нереализованное исключение в базовом классе и не иметь ошибки компиляции, если метод не реализован . Какой дизайн будет лучше? Я думаю, что нет никакого способа обойти это... - person Greg Olmstead; 08.06.2010
comment
Я думал, вам нужно решение только для метода, а уже получилось, что свойства останутся в базовом классе? - person Justin Ethier; 08.06.2010

Вы должны сделать свой базовый класс абстрактным классом. Затем базовый класс может реализовать интерфейс, пометив метод как абстрактный.

http://msdn.microsoft.com/en-us/library/aa664435(VS.71).aspx

person sgriffinusa    schedule 08.06.2010

Отметьте метод как абстрактный в вашем базовом классе. Вам придется реализовать его в производных классах, но базовому классу не нужно будет иметь определение метода.

person Paul Kearney - pk    schedule 08.06.2010

Я согласен с другими, но абстрактный пользовательский элемент управления имеет некоторые проблемы для дизайнера. Дизайнер часто не отображает абстрактный пользовательский элемент управления.

Я бы реализовал методы интерфейса в базовом классе. Вы можете создать исключение NotImplemented или Assert.Fail в методах, если хотите убедиться, что наследники правильно переопределяют эти методы.

person Scott P    schedule 08.06.2010

Объявите сигнатуру функции в базовом классе и используйте модификатор «abstract».

person riwalk    schedule 08.06.2010