Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

И снова про множественное наследование((

73K
08 сентября 2012 года
Villain512
32 / / 08.09.2012
Хочу сделать свои реализации функций и свойств для разных унаследованных контролов, и избежать копипасты кода. То есть хочу, чтобы новые контролы содержали реализации как своего класса, так и общего для всех моих контролов класса. Какие есть пути решения проблемы?
297
10 сентября 2012 года
koodeer
1.2K / / 02.05.2009
Набросал пример кодогенерации с T4.

Код:
using System;
using System.Windows.Forms;

namespace TestApp
{
  <#@ template debug="false" hostspecific="false" language="C#" #>
  <#@ output extension=".cs" #>
  namespace MyApp
  {
    <#
    foreach(string T in new string[] { "Button", "TextBox", "Form" })
    {
    #>      
        public class <#=T#>E : <#=T#>
        {
          public object Tag1 { get; set; }
          public object Tag2 { get; set; }
          public object Tag3 { get; set; }

          public delegate void MyEvent();
          public MyEvent EVENT;

          new public bool Visible
          {
            get
            {
              return (bool)this.Invoke((Func<bool>)(()=>base.Visible));
            }
            set
            {
              this.Invoke((Action)(()=>base.Visible=value));
            }
          }
        }    
    <#
    }
    #>
  }
}
Этот код нужно поместить в файл с расширением tt.
После компиляции будет создаваться файл cs, в котором будет набор классов.
Конечно, не для всех случаев это подойдёт.
Опробовал в VS2010.
Увы, ни подсветки синтаксиса, ни автокомплита, ни интеллисенса... Так что стоит десять раз подумать, упростит ли это работу.
1
08 сентября 2012 года
kot_
7.3K / / 20.01.2000
мультинаследование - зло и источник не очевидных ошибок. А для указанной задачи она еще и не нужна.
414
08 сентября 2012 года
CassandraDied
763 / / 24.05.2012
base.
73K
08 сентября 2012 года
Villain512
32 / / 08.09.2012
Ну раз не нужна, тогда как сделать? Я лично не вижу другого выхода.
1
09 сентября 2012 года
kot_
7.3K / / 20.01.2000
Цитата: Villain512
Ну раз не нужна, тогда как сделать? Я лично не вижу другого выхода.


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

73K
09 сентября 2012 года
Villain512
32 / / 08.09.2012
Я спросил конкретно какие решения? Это как раз та задача, где без него не обойтись.

Еслиб это были все пользовательские классы, то да. тут можно. и то не всегда. А тут один класс стандартный.
40K
09 сентября 2012 года
D129
228 / / 18.04.2012
А интерфейсы на что?

Сделайте общий интерфейс, имплементируйте его во всех нужных классах, а в имплементации используйте вызов утилитной функции для обработки.
Вся "копипаста" сведется к копированию вызова функции.
73K
09 сентября 2012 года
Villain512
32 / / 08.09.2012
Да никак не получиться не копипастить код, с использованием интерфейсов или без них, интерфейсы не содержат реализаций. 1 класс стандартыный а второй мой. как я создам третий и четвертый и тд чтобы они содержали методы из обоих классов без копипасты кода? Вы вообще читали вопрос или нет мой? Просто умничаете такое ощущение.
297
09 сентября 2012 года
koodeer
1.2K / / 02.05.2009
Цитата:
Какие есть пути решения проблемы?


Применить агрегацию или композицию.

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

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

73K
09 сентября 2012 года
Villain512
32 / / 08.09.2012
Методы оно понятно что расширения могут быть, а мне нужны еще свойства, события и тд и тп. КАК мне сделать один общий для всех моих наследованных контролов блок кода??? Без копипасты. Привидите пример, если не можете, то куча слов мне не поможет точно.
40K
09 сентября 2012 года
D129
228 / / 18.04.2012
Цитата: Villain512
Просто умничаете такое ощущение.


Ну, не я один.

А то, что при обьявлении наследования нужно копипастить имя базового класса за двоеточие - вас не смущает?
Тоже знаете ли, далеко от идеала...

:-)
Ну если серьезно - зачем вам быть святее папы римского? Вы считаете, что копипаст в реальных проэктах не применяется?

Зло ведь не прием, а неправильное его использование.

73K
09 сентября 2012 года
Villain512
32 / / 08.09.2012
Копипаста вызывает кучу ошибок и путаницы, особенно когда начинаешь править сразу в куче классов. Поэтому с ней нужно бороться.
40K
09 сентября 2012 года
D129
228 / / 18.04.2012
Цитата: Villain512
Копипаста вызывает кучу ошибок и путаницы, особенно когда начинаешь править сразу в куче классов. Поэтому с ней нужно бороться.



Ну это пишут в учебниках. Но это прием, и он не запрещен. Вызов функции, во первых, может быть неизменным (стандартным )- как object + EventArg в обработчике эвентов, во вторых - даже если - изменить количество аргументов или их тип - это наиболее простое действие из из многих возможных.

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

:-)

297
09 сентября 2012 года
koodeer
1.2K / / 02.05.2009
Цитата: Villain512
Методы оно понятно что расширения могут быть, а мне нужны еще свойства, события и тд и тп.


Наконец-то. Хоть какая-то информация. Что за нубство, - не описывать сразу все необходимые условия?

Цитата: Villain512
КАК мне сделать один общий для всех моих наследованных контролов блок кода??? Без копипасты.


Повторяю ещё раз:

  • агрегация
  • композиция
  • методы-расширения
Также могу предложить кодогенерацию (например T4) - в ряде случаем избавляет от копипаста.

Цитата: Villain512
Привидите пример, если не можете, то куча слов мне не поможет точно.


Приведите пример своего кода, что имеется, и что хочется. Покажите, что агрегация/композиция не подходят. В противном случае - я сочту, что общаюсь с нупом, и прекращу общение.
И, да, нет в C# множественного наследования! Нет! Разговор окончен.

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

297
09 сентября 2012 года
koodeer
1.2K / / 02.05.2009
Цитата: D129
Если вам действительно нужно множественное наследование, и дотнет - у вас не остается другого выбора.
Дотнет писали ребяты поумнее нас с вами, и если уж они что-то выкинули, значит нам же лучше.


Хочу позанудствовать.
Множественного наследования нет в языке C#. Но на платформе .NET реализовано множество разных языков, среди которых есть и языки с множественным наследованием. Например, Eiffel.
Выход: пишем библиотеку на таком языке, и используем её в C#.

73K
09 сентября 2012 года
Villain512
32 / / 08.09.2012
Да считай что угодно. Интересно вопрос поставлен, что я должен показать, что они не работают тут (хотя не пойму каким боком они тут взялись), вместо того, чтобы вы показали что они работают. Вот приведу пример несуществующего множественного наследования, копипастить код из первого класса во все контролы по 100раз нельзя :)


class AddProp:Control
{
public object Tag1{get;set;}
public object Tag2{get;set;}
public object Tag3{get;set;}

public delegate void MyEvent();
public MyEvent EVENT;

new public bool Visible
{
get
{
return (bool)this.Invoke((Func<bool>)(()=>base.Visible));
}
set
{
this.Invoke((Action)(()=>base.Visible=value));
}
}
//и тд и тп, все это должно быть во всех классах
}

class ButtonE : Button, AddProp
{

}
class TextBoxE : TextBox, AddProp
{

}
class FormE : Form, AddProp
{

}
//и прочая куча контролов


То есть каждый контрол должен иметь набор свойств из первого класса
40K
10 сентября 2012 года
D129
228 / / 18.04.2012
Цитата: Villain512
То есть каждый контрол должен иметь набор свойств из первого класса


Ну так вам подсказали про композицию.

Делаете интерфейс, со свойством, которое возвращает некий класс (первый в вашей терминологии) , в этот класс пишите любой набор чего угодно,
и имплементируете этот интерфейс во всех Е контролах. :-)
(Ё мобиль строите?)

Потом любые изменения - только в "первом" классе Но он не должен быть сам контролом - чисто ваш класс, без иерархии.

Для того, чтобы вызывать методы и свойства TextBoxE, который и будет прямым наследником контрола, достаточно будет в методы первого класса передавать параметр типа Control. Вот и будет у них общая база.

В будущем никакого копипаста.

40K
10 сентября 2012 года
D129
228 / / 18.04.2012
А что за проблему вы вот этим решаете?

 
Код:
this.Invoke((Action)(()=>base.Visible=value));
Invoke нужен если вы менять свойства контрола хотите, а тут зачем?
73K
10 сентября 2012 года
Villain512
32 / / 08.09.2012
Интересно каким образом изменения свойства контрола в параллельно существующем классе отразятся на моих наследованных контролах, и вообще зачем тогда делать интерфейс?

Цитата:
Invoke нужен если вы менять свойства контрола хотите, а тут зачем?


Менять свойста контрола.


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


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

297
10 сентября 2012 года
koodeer
1.2K / / 02.05.2009
Цитата: Villain512
Агрегацией конечно решить проблему можно, но придется для вызова свойств контрола прописывать еще класс перед свойством. А этого я делать не хочу.


Увы, только так и придётся делать. Я не вижу других способов для множественного наследования свойств.
Вероятно, можно исхитриться и сделать подобие МН с помощью АОП-фреймворков, но вряд ли это упростит проект, наверняка усложнит, и особенно его поддержку в будущем.


Насчёт хитрого множественного наследования. Есть такой способ:

Код:
// Объявляем пустой интерфейс
interface IFoo { }

// Реализация методов интерфейса
static class Helper
{
    public static void Foo(this IFoo foo)
    {
        Console.WriteLine("foo");
    }
}

// Базовый класс, от которого будем наследоваться
class Base
{
    public void Bar()
    {
        Console.WriteLine("bar");
    }
}

// Это класс наследуется и от базового, и от интерфейса(ов).
// Причём методы интерфейса тоже реализованы!
class A : Base, IFoo { }
В результате в классе A уже реализованы и члены базового класса, и методы интерфейса.
Однако, таким образом можно только методы реализовать. Свойства или поля не получится (их нужно пихать в базовый класс).
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог