Множественное наследование
От: QuAzI Беларусь  
Дата: 10.12.15 14:32
Оценка:
Есть два основных интерфейса и несколько ветвящихся от базового классов.
Логика работы строится исходя из того, какие у класса есть интерфейсы или их вообще нет.
Из-за того что один и тот же интерфейс нужно поддерживать в дочерних классах разных веток, приходится его методы держать в базовом классе (чтобы лишний раз не копипастить).
За сим две проблемы
1) из промежуточных классов торчат методы, которых у них быть не должно (как минимум раздражает на этапе написания кода).
2) народ может пытаться с ними работать, хотя должен работать только с классами у которых чётко прослеживается интерфейс.
В плюсах это решилось бы просто, из базового класса всё выкинулось бы и определилось бы в другом классе от которого бы дополнительно наследовались только нужные классы.
А в C# как с этим бороться? Можно ли как-то у дочернего класса задавить то что определено в базовом, а потом снова открыть в нужном потомке?

Примерная диаграмма ветвления классов
множественное наследование c#
Re: Множественное наследование
От: Qulac Россия  
Дата: 10.12.15 15:16
Оценка:
Здравствуйте, QuAzI, Вы писали:

QAI>Есть два основных интерфейса и несколько ветвящихся от базового классов.

QAI>Логика работы строится исходя из того, какие у класса есть интерфейсы или их вообще нет.
QAI>Из-за того что один и тот же интерфейс нужно поддерживать в дочерних классах разных веток, приходится его методы держать в базовом классе (чтобы лишний раз не копипастить).
QAI>За сим две проблемы

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


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

QAI>2) народ может пытаться с ними работать, хотя должен работать только с классами у которых чётко прослеживается интерфейс.

QAI>В плюсах это решилось бы просто, из базового класса всё выкинулось бы и определилось бы в другом классе от которого бы дополнительно наследовались только нужные классы.
QAI>А в C# как с этим бороться? Можно ли как-то у дочернего класса задавить то что определено в базовом, а потом снова открыть в нужном потомке?

Задавить можно, но только другим методом, так что смысла нет.

QAI>Примерная диаграмма ветвления классов

QAI>Image: zo9OyZN.png

Как то так...
Программа – это мысли спрессованные в код
Re: Множественное наследование
От: Sinix  
Дата: 10.12.15 16:32
Оценка: 2 (1) +1
Здравствуйте, QuAzI, Вы писали:

QAI>А в C# как с этим бороться? Можно ли как-то у дочернего класса задавить то что определено в базовом, а потом снова открыть в нужном потомке?


Три стандартных способа:
1. Логика в protected-методах, наследники выставляют в public.
2. Переиспользуемая логика в отдельном классе, инстанс класса хранится в поле, методы интерфейса вызывают код из класса.
3. Любой il weawer/emitter, позволяющий автоматизировать п.2. Fody/Automapper, если навскидку.

На практике самый простой способ — пересмотреть подход к проектированию. Если не секрет — поделитесь реальной задачей, на которой без множественного наследования прям вообще никак. Интересно ж
P.S. Размышления на тему от Липперта, в пяти частях.
Re[2]: Множественное наследование
От: hardcase Пират http://nemerle.org
Дата: 10.12.15 23:05
Оценка: 38 (1)
Здравствуйте, Sinix, Вы писали:

S>На практике самый простой способ — пересмотреть подход к проектированию. Если не секрет — поделитесь реальной задачей, на которой без множественного наследования прям вообще никак. Интересно ж


Например AST для пространств имен и классов.

ast NamespaceMember { DeclaredIn : Namespace; }
ast ClassMember     { DeclaredIn : Class; }

ast Namespace : NamespaceMember { ... }
ast Class { ... }

ast TopClass    : Class, NamespaceMember {}   // DeclaredIn: Namespace
ast NestedClass : Class, ClassMember  {}      // DeclaredIn: Class


Это псевдокод, в реальности там много всяких свойств и настоящее наследование реализации (вычислений).
/* иЗвиНите зА неРовнЫй поЧерК */
Re[3]: Множественное наследование
От: Sinix  
Дата: 11.12.15 06:05
Оценка: 3 (1)
Здравствуйте, hardcase, Вы писали:

S>>Если не секрет — поделитесь реальной задачей, на которой без множественного наследования прям вообще никак.

H>Например AST для пространств имен и классов.

Ага, спасиб! Отдельное спасибо за пример, ещё один способ решения вспомнил, аля MS.Cci/Roslyn:
        // GenericNestedTypeInstanceReference.cs
        public override Cci.INestedTypeReference AsNestedTypeReference
        {
            get { return this; }
        }

        // GenericNamespaceTypeInstanceReference.cs
        public override Microsoft.Cci.INestedTypeReference AsNestedTypeReference
        {
            get { return null; }
        }

В чём прелесть: этот вариант и контракты документирует, и со всеми перечисленными выше способами (в т.ч. и твоим) совместим.
Отредактировано 11.12.2015 6:06 Sinix . Предыдущая версия .
Re[4]: Множественное наследование
От: QuAzI Беларусь  
Дата: 11.12.15 23:00
Оценка:
Здравствуйте, Sinix, Вы писали:

S>Здравствуйте, hardcase, Вы писали:


S>>>Если не секрет — поделитесь реальной задачей, на которой без множественного наследования прям вообще никак.

H>>Например AST для пространств имен и классов.

S>Ага, спасиб! Отдельное спасибо за пример, ещё один способ решения вспомнил, аля MS.Cci/Roslyn:

S>
S>        // GenericNestedTypeInstanceReference.cs
S>        public override Cci.INestedTypeReference AsNestedTypeReference
S>        {
S>            get { return this; }
S>        }

S>        // GenericNamespaceTypeInstanceReference.cs
S>        public override Microsoft.Cci.INestedTypeReference AsNestedTypeReference
S>        {
S>            get { return null; }
S>        }
S>

S>В чём прелесть: этот вариант и контракты документирует, и со всеми перечисленными выше способами (в т.ч. и твоим) совместим.

Спасибо, интересные варианты.
В принципе почти сразу после поста я сделал всё через protected в базовом классе и раскрыл как public в классах поддерживающих интерфейсы. Правда чтобы не переопределять через new исользовал троху кривое именование, m_ префикс для свойств и суффикс _internal для методов. Не уверен что красивое решение, но чтобы не путаться как-то так решил их обозначить.
По последнему примеру что-то наглядное кроме сорсов собственно рослина не гуглится, а я как-то туплю и не понимаю как этот подход поюзать в .NET2/.NET4

Про дизайн — возможно вы правы, но уж как есть, переписывать с нуля слишком дорого и мне пока не хватает опыта/мозгов, чтобы задизайнить мою задачу лучше.
Re[5]: Множественное наследование
От: Sinix  
Дата: 13.12.15 13:41
Оценка:
Здравствуйте, QuAzI, Вы писали:

QAI>Правда чтобы не переопределять через new исользовал троху кривое именование, m_ префикс для свойств и суффикс _internal для методов. Не уверен что красивое решение, но чтобы не путаться как-то так решил их обозначить.

Обычно добавляют суффиксы Core, Internal или Impl, но это уже из разряда про вкус фломастеров.

QAI>По последнему примеру что-то наглядное кроме сорсов собственно рослина не гуглится, а я как-то туплю и не понимаю как этот подход поюзать в .NET2/.NET4

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

QAI>Про дизайн — возможно вы правы, но уж как есть, переписывать с нуля слишком дорого и мне пока не хватает опыта/мозгов, чтобы задизайнить мою задачу лучше.

А, если код уже написан, то разумеется не надо его бросаться заменять без явной необходимости. Я понял вопрос как "как спроектировать", потому и посоветовал
Re[2]: Множественное наследование
От: DarthSidius  
Дата: 14.12.15 02:06
Оценка: +1
Здравствуйте, Sinix, Вы писали:

S>Здравствуйте, QuAzI, Вы писали:


QAI>>А в C# как с этим бороться? Можно ли как-то у дочернего класса задавить то что определено в базовом, а потом снова открыть в нужном потомке?


S>Три стандартных способа:

S>1. Логика в protected-методах, наследники выставляют в public.
S>2. Переиспользуемая логика в отдельном классе, инстанс класса хранится в поле, методы интерфейса вызывают код из класса.

Для интерфейсов также можно писать extension методы
... << RSDN@Home (RF) 1.2.0 alpha 5 rev. 58>>
♠♠♥♠♠♦♥
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.