C# интерфейсы наследование

Интерфейсы и наследование — верно ли понята суть

Почитал про интерфейсы и их наследование, и вычитал что они являются аналогом наследования от нескольких классов.

Я правильно понимаю, что если класс создается на основе интерфейса, который был унаследован от другого интерфейса, то создаваемый класс на основе симбиоза этих двух интерфейсов, должен реализовать методы двух интерфейсов?
А так же при обращение через новый интерфейс(Который был создан из 2 ух), я правильно понимаю, что не смогу обращаться к классам в которых был реализован только один из интерфейсов?

Интерфейсы — в чем их суть
В чем суть интерфейсов объясните пожалуйста. Добавлено через 19 минут А.

Наследование и интерфейсы
Один класс может реализовывать более одного интерфейса. А может ли один класс.

Интерфейсы или наследование
Добрый день, помогите с реализацией программы: Я хочу написать в консоли.

Наследование через интерфейсы
Добрый вечер. Начал делать программу и появилась проблема с наследованием.

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

Интерфейсы. Выделить у классов общий интерфейс(или интерфейсы)
Задание: У классов выделить общий интерфейс ( или интерфейсы ). первый класс.

www.cyberforum.ru

C# интерфейсы наследование

У тех, кто только начинает осваивать C# часто возникает вопрос что такое интерфейс и зачем он нужен.

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

Соответственно, если какой-то класс реализует данный интерфейс, то он должен содержать реализацию метода int GetForecast(int value) и свойство Size.

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

Подводя итог этой части, если какой-то интерфейс реализуется только в одном единственном классе, то не тратьте время на него. Он просто не нужен.

Дополнение
Сразу после публикации на меня обрушили море критики, сначала я пытался отвечать, но потом понял, что смысла нет. Все критики упирают на то, что я написал в предыдущем абзаце и пытаются приводить сложные примеры проектов где много классов, всякие ссылки туда-сюда, поддержка командой и прочее. Я наверно был не прав, что так коротко подвел итог вступления. Но суть в том, что интерфейс нужен далеко не всегда. Если у вас ваш личный (или просто не очень большой) проект, который не планируется масштабировать, на который ни кто не ссылается и, самое главное, который успешно работает, то введение в проект интерфейсов ничего не изменит. И не надо придумывать истории, что где-то кто-то однажды реализовал интерфейс и обрел бессмертие. Если бы интерфейс был нужен везде, он был бы неотъемлемой частью класса.

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

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

Например, предположим у нас есть два класса:

Это два совсем разных класса, но пусть у них будет что-то общее, т.е. мы хотим, чтобы один метод работал с ними обоими без дополнительной логики. В таком случае мы можем реализовать общий интерфейс, т.е. объявить эти классы как

Теперь мы можем сделать общий метод для них:

Как видно, переменная value получит значение функции GetForecast от того класса, который будет передан в качестве параметра без дополнительных действий по приведению типов и т.п.

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

Можно пойти еще дальше и объявить массив (или list) таких объектов:

А потом можно например вычислить сумму всех свойств Size:

У объявления через интерфейс есть один недостаток: вам будут доступны только методы и свойства, объявленные в интерфейсе и самом классе. Если ваш класс унаследован от базового, то для доступа к его методам придется делать приведение типа:

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

Например добавим в наш проект еще один интерфейс:

И создадим новый класс, наследующий оба интерфейса:

Это называется явной реализацией интерфейса. Теперь можно построить такую конструкцию:

Интересно, что при реализации таких интерфейсов методам не могут быть назначены модификаторы доступа (“public” или что-то еще), однако они вполне доступны как публичные через приведение типа.

Как видно, это работает, но выглядит слишком громоздко. Чтобы как-то улучшить код, можно написать несколько иначе:

bad и good будут ссылаться на third, но иметь в виду разные интерфейсы. Привидение можно сделать один раз, а его результат потом использовать многократно. Возможно, что в некоторых случаях это сделает код более читаемым.

Еще одно применение интерфейса — быстрое изготовление заглушек для функций.
Например, вы в команде строите большой проект и ваш класс зависит от класса, который пишет коллега. Но еще не написал. Мудрый начальник подготовил интерфейсы всех основных классов еще на первом этапе разработки проекта и вы теперь можете не ждать коллегу, а реализовать класс-заглушку для своего класса. Т.е. временный класс не будет содержать логики, а будет только делать вид что работает: принимать вызовы и возвращать адекватные значения. Для этого надо только реализовать тот же интерфейс, что получил ваш коллега.

Работающий проект со всеми примерами из этой статьи можно посмотреть здесь: ссылка

m.habr.com

Множественное наследование в C#

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

Как в таком случае они могут заменить множественное наследование? Допустим у меня есть два класса — A и B. Я хочу создать классы C, D и E. Каждый из этих классов должен включать в себя методы как класса A, так и класса B. На сколько я понял логику интерфейсов, для реализации моей задумки мне придётся описать два интерфейса — IA и IB. После чего объявить, что класс A реализует интерфейс IA, класс B — IB, а классы C, D и E оба этих интерфейса сразу. Всё бы хорошо, но только код функций каждого интерфейса придётся воспроизводить в каждом классе заново.

Я ничего не перепутал? 🙂

20 ответов

Не совсем. Стопроцентно можно избежать дублирования кода. Просто классы A, B, C, D, E немного абстрактны, для построения правильной иерархии. Если приведете конкретный пример, будет легче.

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

Угу. Кое чего можно сделать через генерики. Максимально эффективная связка в C# это генерики + интерфейсы. Хотя мне их выразительной возможности метами нехватает, приходится отражать.

Теперь, как мне спарить этих двух зверушек, что бы получился Пегас, которой умеет скакать и летать, без дублирования кода соответствующих методов? На C++ это выглядело бы так:

А как это будет выглядеть при использовании интерфейсов?

class CPegas
<
public CPegas()
<
__Horse = new CHorse();
__Bird = new CBird();
>

private CHorse __Horse;
private CBird __Bird;

public void ride()
<
__Horse.ride();
>

Вот стандартный подход. Pegasus — композитный объект, содержит в себе Bird и Horse.

public interface IHorse <
void Ride();
>

public interface IBird <
void Fly();
>

public class Horse : IHorse <
public void Ride() <
>
>

public class Bird : IBird <
public void Fly() <
>
>

public interface IPegasus : IHorse, IBird <
>

public class Pegasus : IPegasus <
private Horse _horse = new Horse();

private Bird _bird = new Bird();

public void Ride() <
_horse.Ride();
>

Вспоминается тот самый Ping с его диспоузом 😀

Мне тоже кажется, что эта возможность имеет сомнительный характер: ни разу мне не пригодилась. Но я допускаю, что могу просто чего-то не знать или банально не понимать. Как бы я вижу, что .NET умные дядьки сочиняли, и введение подобной двусмысленности должно иметь под собой какую-то почву, наверное. Можно и обсудить.
Предполагаемые мной предпосылки:
— принцип подстановки Барбары Лискофф в формулировке Роберта Мартина: методы, принимающие в качестве параметра указатели и ссылки на объекты базового класса, должны иметь возможность использовать эти объекты без необходимости знать, к какому классу (базовому или любому из производных) они принадлежат (один из базовых принципов ООП-дизайна);
— видимо, даже при тщательном планировании дизайна, средствами обычного полиморфизма (возможно именно полиморфизма .NET, хотя разницы не вижу) не всегда можно обеспечить выполнение вышеприведённого принципа;
— возможно, это имеет какое-то отношение к разрешению конфликтов имён методов реализуемых интерфейсов.
Лично мне кажется, что необходимость применения явной реализации интерфейсов в последних двух случаях обусловлена неверным дизайном. Кто-нибуть встречал инциденты подобного?

Пожалуй, это единственный убедительный аргумент.
К примеру, этот способ используется при реализации параметрического интерфейса IEnumerable . При этом нужно реализовывать два метода GetEnumerator — строго типизированный и нестрогий.

С моей точки зрения, конкретно интерфейсов (в .NET-ной трактовке) недостаточно. Мне иногда остро недостает подобия контрактов — своего рода «интерфейсов времени компиляции». Когда мы декларируем компилятору, что вот данный объект должен поддерживать такие-то и такие-то свойства-методы. Обосновано это тем, что зачастую не важен конкретный тип объекта — важен сам факт наличия у объекта набора тех или иных свойств-методов. Замечу, что полиморфизм такого уровня невозможен в C#, но вполне реализуем в Nemerle.

Ну раз тут всё так описано, то вот у меня как раз по теме вопрос:
Есть базовый класс

public abstract Objectbase<>

public abstract ObjectManagerBase where T : ObjectBase, new()
<

public abstract T Create(DataRow dr);
.
>

Наследники ObjectManagerBase , например UserManager , управляют объектами User, не имеющими языковой поддержки,
но имеются так же объекты типа Category, логика создания которых идетнична User, но для каждой страны у них своё имя и ещё кое какие специфичные для данной страны свойства.
Для создания объекта LanguageSupport торчащего через свойство Category.LanguageSupport есть соответсвующий метод,
который приходится дублировать во всех наследниках ObjectManagerBase , управляющий объектами с языковой поддержкой.

По идее было бы замечательно создать ещё один базовый класс типа

public abstract LanguageSupportedOjectManagerBase where T : LanguageSupport, new()
<

public T Create(DataRow dr)
<
T languageSupport = new T();
.
return languageSupport;
>
>

и создать класс CategoryManager, наследующий от ObjectManagerBase и LanguageSupportedOjectManagerBase , но так в .net нельзя.

Возможно ли добавть функционал базового класса LanguageSupportedOjectManagerBase к некоторым наследникам ObjectManagerBase ?

forum.codenet.ru

Интерфейсы. Множественное наследование

Множественное наследование и его проблемы

Множественным наследованием называется ситуация, когда класс объявляет N классов ( N > 1 ) своими непосредственными родителями. В языке C# есть ограничения на множественное наследование . Ситуация здесь такая. Во-первых, у каждого класса родителем, хотя не всегда непосредственным, является класс object . Во-вторых, каждый класс может явно объявить один класс в качестве непосредственного родителя, а также объявить непосредственными родителями один или несколько интерфейсов. Таким образом, в C# допускается множественное наследование интерфейсов и одиночное (не считая наследования от класса object ) наследование классов.

Во многом ограничение множественного наследования классов связано с тем, что оно создает ряд проблем. Они остаются и при множественном наследовании интерфейсов, хотя становятся проще. Рассмотрим две основные проблемы — коллизию имен и наследование от общего предка.

Коллизия имен

Проблема коллизии имен возникает, когда два или более интерфейса имеют методы с одинаковыми именами и сигнатурой. Если сигнатуры разные, то это не приводит к конфликтам. Класс реализует методы обоих интерфейсов, и у него просто появляются перегруженные методы .

Но что следует делать классу наследнику в тех случаях, когда сигнатуры методов совпадают? Возможны две стратегии — склеивание методов и переименование.

Стратегия склеивания применяется тогда, когда класс — наследник интерфейсов — полагает, что методы разных интерфейсов, имеющие одинаковое имя и сигнатуру, задают один и тот же метод, единая реализация которого и должна быть обеспечена наследником. В этом случае наследник строит единственную общедоступную ( public ) реализацию, соответствующую методам всех интерфейсов c единой сигнатурой.

Стратегия переименования исходит из того, что, несмотря на единую сигнатуру, методы разных интерфейсов должны быть реализованы по-разному. В этом случае необходимо переименовать конфликтующие методы. Конечно, переименование можно сделать в самих интерфейсах, но это неправильный путь: наследники не должны требовать изменений своих родителей — они сами должны меняться. Переименование методов интерфейсов иногда невозможно чисто технически, если интерфейсы являются встроенными или поставляются сторонними фирмами. К счастью, мы уже знаем, как производить переименование метода интерфейса в самом классе наследника. Для этого достаточно реализовать в классе методы разных интерфейсов как закрытые, а затем открыть их в классе с переименованием.

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

Наследование от общего предка

Проблема наследования от общего предка характерна, в первую очередь, для множественного наследования классов. Если класс C является наследником классов A и B , а те, в свой черед, являются наследниками класса P , то класс наследует свойства и методы своего предка P дважды: один раз получая их от класса A , другой — от B . Это явление называется еще дублирующим наследованием. Для классов ситуация осложняется тем, что классы A и B могли по-разному переопределить методы родителя и для потомков предстоит сложный выбор реализации. Ситуация дублирующего наследования показана на рис. 5.3.

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

Склеивание и переименование

Приведу пример двух интерфейсов, имеющих методы с одинаковой сигнатурой, и класса — наследника этих интерфейсов, применяющего разные стратегии для конфликтующих методов. У нас уже определен интерфейс IStrings . Предположим, что существует интерфейс ITransform , подобный Istrings :

У этих интерфейсов имена и сигнатуры методов совпадают. Вот класс, наследующий оба интерфейса:

Для методов Cipher двух интерфейсов выбрана стратегия склеивания. Для методов Convert выбрана стратегия переименования. Методы интерфейсов реализованы как закрытые методы , а затем в классе объявлены два новых метода с разными именами, являющиеся обертками закрытых методов класса.

Приведу пример работы с объектами класса и интерфейсными объектами:

www.intuit.ru

Множественное наследование в C# для свойств (или параметров функций)

Такая ситуация: определены несколько интерфейсов (например: IMyInterface1, IMyInterface2, . ). В классе MyClass есть свойство IMyInterface MyProperty < get; set; >.

Хотелось бы, чтобы свойство реализовывало сразу два-три интерфейса (примерно как это может делать класс) без потери строгой типизации.

Насколько знаю — синтаксис C# это не позволяет. Создавать на каждую связку интерфейсов отдельный тип не хочется (получится слишком много комбинаций). Создавать связку свойств, каждое из которых реализует отдельный интерфейс — это тоже как-то криво.

Наследование интерфейсов предлагаю не обсуждать, так как это нехорошо (наследование — лишь эффектный способ избежать дублирования кода). Интерфейсы независимые.

Какие есть предложения?

Есть два интерфейса: «НажимабельнаяКнопка» и «ЦветнаяКнопка». Я хочу, чтобы свойство «НажимабельнаяЦветнаяКнопка» класса «МояФорма» как-нибудь реализовывало сразу оба этих интерфейса.

Сейчас мне приходится делать два отдельных свойства. Как их объединить в одно? (код ClickableColorButton < get; set; >не прокатит, это я для понятности написал)

В конечном итоге пришли к вопросу «зачем это может быть нужно?» Согласен — задача редко встречающаяся. А цель одна — снижение взаимосвязи блоков кода.

Допустим, мы создаем классы-контроллеры, управляющие формами пользовательского интерфейса. Контроллеры работают не напрямую с классами, а через интерфейс. В большинстве случаев контроллеру достаточно подписываться на событие нажатия «НажимабельнойКнопки» и обрабатывать его. Но в один из двадцати контроллеров, например, не только обрабатывает клик, но и должен менять цвет этой кнопки. А еще пара контроллеров кроме клика должна менять текст на кнопке. Конечно, можно создать интерфейс сразу с «кликом», «цветом» и «текстом». Но ведь бОльшей части контроллеров остальные свойства вообще не нужны — им достаточно только клика. Вот и возникает задача — как бы передавать свойства «цвет» или «текст» только в тех редких случаях, когда они действительно необходимы.

И еще один момент — если код покрывается модульными тестами — в качестве подопытных объектов бывает нужно подсовывать mock-и. Чем проще интерфейсы, тем легче эти mock-объекты формировать.

Наверно, кто-то скажет что это уже излишнее абстрагирование, чересчур подробное — возможно… Но меня тут интересует — есть ли возможность. А в какой степени ее применять — это уже другой вопрос.

toster.ru

Смотрите так же:

  • Мордовия гражданство рф Мордовия приглашает соотечественников из-за рубежа Мордовия готова принять соотечественников, решивших вернуться на родину из-за рубежа. Переселенцам готовы помочь материально, а главное - в короткие сроки решить вопрос с получением […]
  • Размер пенсии для инвалидов второй группы Пенсия по инвалидности 2 группы в 2018 году Присвоение любых форм инвалидности в России происходит исключительно по медико-социальным показателям. Назначение инвалидности 2 категории допустимо для людей, считающихся нетрудоспособными, но […]
  • Размер госпошлины за обеспечительные меры Госпошлина в арбитражный суд: 2017 год Актуально на: 19 июня 2017 г. Заявление на возврат излишне уплаченной государственной пошлины Одной из разновидностью госпошлин является государственная пошлина в арбитражный суд. Об особенностях […]
  • Расчет пенсии инвалидам 2 группы Пенсия по инвалидности 2 группы в 2018 году Присвоение любых форм инвалидности в России происходит исключительно по медико-социальным показателям. Назначение инвалидности 2 категории допустимо для людей, считающихся нетрудоспособными, но […]
  • Пособия по безработице в россии в 2014 Размеры пособия по безработице в 2014 году останутся прежними Утверждены размеры минимальной и максимальной величин пособия по безработице на 2014 год. Правительством РФ 30 октября 2013 года подписано соответствующее постановление. Так, в […]
  • Образец соглашение о возврате долга Соглашение о погашении задолженности При исполнении денежных обязательств, стороны могут использовать соглашение о погашении задолженности в целях фиксации суммы долга и штрафных санкций. Такой документ применяется в качестве одного из […]

Обсуждение закрыто.