Множественное наследование в C# для свойств (или параметров функций) Такая ситуация: определены несколько интерфейсов (например: IMyInterface1, IMyInterface2, ...). В классе MyClass есть свойство IMyInterface MyProperty { get; set; }.
Хотелось бы, чтобы свойство реализовывало сразу два-три интерфейса (примерно как это может делать класс) без потери строгой типизации.
Насколько знаю — синтаксис C# это не позволяет. Создавать на каждую связку интерфейсов отдельный тип не хочется (получится слишком много комбинаций). Создавать связку свойств, каждое из которых реализует отдельный интерфейс — это тоже как-то криво.
Наследование интерфейсов предлагаю не обсуждать, так как это нехорошо (наследование — лишь эффектный способ избежать дублирования кода). Интерфейсы независимые.
Какие есть предложения? interface IClickableButton { event Action Click; } interface IColorButton { Color Color { get; set; } } class MyForm { public IClickableButton ClickableButton { get; set; } public IColorButton ColorButton { get; set; } public ClickableColorButton { get; set; } }
Есть два интерфейса: «НажимабельнаяКнопка» и «ЦветнаяКнопка». Я хочу, чтобы свойство «НажимабельнаяЦветнаяКнопка» класса «МояФорма» как-нибудь реализовывало сразу оба этих интерфейса.
Сейчас мне приходится делать два отдельных свойства. Как их объединить в одно? (код ClickableColorButton { get; set; } не прокатит, это я для понятности написал)
P. P. S.:
В конечном итоге пришли к вопросу "зачем это может быть нужно?" Согласен — задача редко встречающаяся. А цель одна — снижение взаимосвязи блоков кода.
Допустим, мы создаем классы-контроллеры, управляющие формами пользовательского интерфейса. Контроллеры работают не напрямую с классами, а через интерфейс. В большинстве случаев контроллеру достаточно подписываться на событие нажатия «НажимабельнойКнопки» и обрабатывать его. Но в один из двадцати контроллеров, например, не только обрабатывает клик, но и должен менять цвет этой кнопки. А еще пара контроллеров кроме клика должна менять текст на кнопке. Конечно, можно создать интерфейс сразу с «кликом», «цветом» и «текстом». Но ведь бОльшей части контроллеров остальные свойства вообще не нужны — им достаточно только клика. Вот и возникает задача — как бы передавать свойства «цвет» или «текст» только в тех редких случаях, когда они действительно необходимы.
И еще один момент — если код покрывается модульными тестами — в качестве подопытных объектов бывает нужно подсовывать mock-и. Чем проще интерфейсы, тем легче эти mock-объекты формировать.
Наверно, кто-то скажет что это уже излишнее абстрагирование, чересчур подробное — возможно… Но меня тут интересует — есть ли возможность. А в какой степени ее применять — это уже другой вопрос.
P. P. P. S.: подходящее для меня решение описано тут: habrahabr.ru/blogs/net/123229 Пока писал топик, пользователь tenbits предложил точно такое же решение.
Спасибо за подробные пояснения! Для вашего случая действительно имеется подходящее решение — использование комбинированных интерфейсов. Это позволит вам создать один интерфейс, который будет объединять в себе свойства и методы нескольких интерфейсов.
В вашем случае, вы можете создать комбинированный интерфейс, который будет содержать свойства и методы как от IClickableButton, так и от IColorButton, например:
interface IClickableColorButton : IClickableButton, IColorButton { // дополнительные свойства и методы, если необходимо }
Затем вы можете использовать этот комбинированный интерфейс в вашем классе MyForm:
class MyForm { public IClickableButton ClickableButton { get; set; } public IColorButton ColorButton { get; set; } public IClickableColorButton ClickableColorButton { get; set; } }
Теперь свойство ClickableColorButton будет реализовывать все свойства и методы и от IClickableButton, и от IColorButton. Таким образом, вы избежите дублирования кода и сможете сохранить строгую типизацию.
Надеюсь, это поможет вам решить вашу задачу! Если у вас возникнут дополнительные вопросы, не стесняйтесь задавать.
Спасибо за подробные пояснения! Для вашего случая действительно имеется подходящее решение — использование комбинированных интерфейсов. Это позволит вам создать один интерфейс, который будет объединять в себе свойства и методы нескольких интерфейсов.
В вашем случае, вы можете создать комбинированный интерфейс, который будет содержать свойства и методы как от IClickableButton, так и от IColorButton, например:
interface IClickableColorButton : IClickableButton, IColorButton{
// дополнительные свойства и методы, если необходимо
}
Затем вы можете использовать этот комбинированный интерфейс в вашем классе MyForm:
class MyForm{
public IClickableButton ClickableButton { get; set; }
public IColorButton ColorButton { get; set; }
public IClickableColorButton ClickableColorButton { get; set; }
}
Теперь свойство ClickableColorButton будет реализовывать все свойства и методы и от IClickableButton, и от IColorButton. Таким образом, вы избежите дублирования кода и сможете сохранить строгую типизацию.
Надеюсь, это поможет вам решить вашу задачу! Если у вас возникнут дополнительные вопросы, не стесняйтесь задавать.