Псевдо-множественное наследование с методами расширения на интерфейсах в C #? - PullRequest
6 голосов
/ 30 мая 2009

Аналогичный вопрос, но не совсем то же самое

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

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

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

Ответы [ 2 ]

4 голосов
/ 30 мая 2009

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

Скажем, у меня есть метод, который принимает объект типа IBar. Если я реализую интерфейс IBar в классе Foo с помощью методов расширения, то Foo не наследуется от IBar и не может использоваться с ним взаимозаменяемо (принцип подстановки Лискова). Конечно, я получаю поведение, которое я хочу добавить в Foo, но я теряю самый важный аспект создания интерфейсов - возможность определять абстрактный контракт, который может быть реализован различными способами различными классами, так что зависимые классы не должны знать о конкретных реализациях.

Если бы мне нужно было достаточно многократное наследование (и до сих пор я без него), я бы вместо этого использовал композицию, чтобы минимизировать количество дублирования кода.

1 голос
/ 04 июня 2009

Приличный способ думать об этом - это то, что методы экземпляра - это что-то, сделанное с помощью объекта, а методы расширения - это то, что делается от до объекта. Я вполне уверен, что в Руководстве по проектированию фреймворка сказано, что вам следует по возможности реализовывать метод экземпляра.

Интерфейс объявляет: «Я забочусь об использовании этой функциональности, но не о том, как она выполняется». Это оставляет исполнителям свободу выбора как. Он отделяет намерение, публичный API, от механизма, класса с конкретным кодом.

Поскольку это является основным преимуществом интерфейсов, их полная реализация в качестве методов расширения, по-видимому, противоречит их цели. Даже IEnumerable<T> имеет метод экземпляра.

Редактировать : Кроме того, объекты должны воздействовать на данные, которые они содержат. Методы расширения могут видеть только открытый API объекта (поскольку они являются просто статическими методами); вам нужно было бы раскрыть все состояния объекта, чтобы он работал (OO no-no).

...