Множественное наследование
От: Аноним  
Дата: 21.07.04 08:40
Оценка:
На одном собеседовании был вопрос: возможно ли на C# реализовать как-нибудь множественное наследование (дабы не переписывать написанный код).

Я ответил что-то в духе того что в общем случае вроде бы нет. Они как-то странно посмотрели И кстати потом не взяли...

Какой правильный ответ?
Re: Множественное наследование
От: trolik Россия  
Дата: 21.07.04 08:43
Оценка: +1
Здравствуйте, Аноним, Вы писали:

А>На одном собеседовании был вопрос: возможно ли на C# реализовать как-нибудь множественное наследование (дабы не переписывать написанный код).


А>Я ответил что-то в духе того что в общем случае вроде бы нет. Они как-то странно посмотрели И кстати потом не взяли...


А>Какой правильный ответ?


Не возможно. А что за частные случаи когда ты думаешь что возможно?
Re: Множественное наследование
От: TK Лес кывт.рф
Дата: 21.07.04 09:00
Оценка:
Hello,
> На одном собеседовании был вопрос: возможно ли на C# реализовать как-нибудь множественное наследование (дабы не переписывать написанный код).
>
> Я ответил что-то в духе того что в общем случае вроде бы нет. Они как-то странно посмотрели И кстати потом не взяли...
> Какой правильный ответ?

Есть множественное наследование интерфейсов. Дальше можно реализовать автоматическое аррегирование реализаций уже написанных классов и используя множественное наследование интерфейсов можно имитировать обычное множественное наследование.
Posted via RSDN NNTP Server 1.9 alpha
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
Re[2]: Множественное наследование
От: Vitaton Россия  
Дата: 21.07.04 09:13
Оценка:
Здравствуйте, TK, Вы писали:


TK>Есть множественное наследование интерфейсов. Дальше можно реализовать автоматическое аррегирование реализаций уже написанных классов


В двух словах, как?
Useless lamer
Re[2]: Множественное наследование
От: s.ts  
Дата: 21.07.04 09:15
Оценка:
Hello, TK!

T> Hello,

??>> На одном собеседовании был вопрос: возможно ли на C# реализовать
??>> как-нибудь множественное наследование (дабы не переписывать написанный
??>> код). Я ответил что-то в духе того что в общем случае вроде бы нет.
??>> Они как-то странно посмотрели И кстати потом не взяли... Какой
??>> правильный ответ?

T> Есть множественное наследование интерфейсов. Дальше можно реализовать

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

Вопрос: как можно реализовать "автоматическое аррегирование реализаций уже написанных классов" ?

p.s.
Вообще, по моему, если так рассуждать, то и на си (просто си) можно множественное наследованяие реализовать "как-нибудь", даже не смотря на то, что в языке классов нет.
Вроде бы отличие наследования от агрегирования как раз и заключается в том, что не нужно делегировать реализацию кому-либо. Грубо говоря, эта самая ссылка на родителя автоматически создается компилятором (на родительскую vmt), а частично код родителя (грубо говоря) копируется в потомка (тоже компилятором).
Posted via RSDN NNTP Server 1.9 beta
Re[3]: Множественное наследование
От: TK Лес кывт.рф
Дата: 21.07.04 09:20
Оценка: 2 (1)
Hello, "Vitaton"
>
>
> TK>Есть множественное наследование интерфейсов. Дальше можно реализовать автоматическое аррегирование реализаций уже написанных классов
>
> В двух словах, как?

В двух словах — есть класс реализующий интерфейс IImplementation, есть класс и CompoundObject для класса CompoundObject определяем фабрику класса котрая делает следущее — генерирует новый класс, наследник CompoundObject добавляя в него поле содержащее ссылку на класс реализующий IImplementation и сам интерфейс IImplementation реализация которого заключается в делегировании всех вызовов через добавленное поле. После этого фабрика возвращает ссылку на созданный экземпляр уже нового класса.
Если поискать на форуме, то можно найти пример реализации.
Posted via RSDN NNTP Server 1.9 alpha
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
Re[3]: Множественное наследование
От: TK Лес кывт.рф
Дата: 21.07.04 09:24
Оценка:
Hello, "s.ts"
>
> Вопрос: как можно реализовать "автоматическое аррегирование реализаций уже написанных классов" ?
>

System.Reflection.Emit и жедание.

> p.s.

> Вообще, по моему, если так рассуждать, то и на си (просто си) можно множественное наследованяие реализовать "как-нибудь", даже не смотря на то, что в языке классов нет.

Естественно, множественного наследования классов в .NET как не крути — нет. Но, можно создавать суррогаты которые при желании помогут достаточно прозрачно получить нужную функциональность.
Posted via RSDN NNTP Server 1.9 alpha
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
Re[4]: Множественное наследование
От: IT Россия linq2db.com
Дата: 21.07.04 14:03
Оценка:
Здравствуйте, TK, Вы писали:

TK>Естественно, множественного наследования классов в .NET как не крути — нет. Но, можно создавать суррогаты которые при желании помогут достаточно прозрачно получить нужную функциональность.


А статейку забульбенить?
... << Rsdn@Home 1.1.4 beta 1 >>
Если нам не помогут, то мы тоже никого не пощадим.
Re[5]: Множественное наследование
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 21.07.04 14:08
Оценка: +6
Здравствуйте, IT, Вы писали:

IT>А статейку забульбенить?


А оно кому нибудь надо? ИМХО в реальности никто этим пользоваться не будет.
... << RSDN@Home 1.1.4 beta 2 >>
AVK Blog
Re[6]: Множественное наследование
От: Silver_s Ниоткуда  
Дата: 21.07.04 14:18
Оценка: +1
Здравствуйте, AndrewVK, Вы писали:

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


IT>>А статейку забульбенить?


AVK>А оно кому нибудь надо? ИМХО в реальности никто этим пользоваться не будет.


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


interface IBase2:IBase1
{
  //....
}

class C : IBase2
{
   IBase1 _b;
   C(IBase1 b){_b=b;}
   
   void IBase2.Func1(){_b.Func1();}
   void IBase2.Func2(){_b.Func2();}
   //...
   //и.т.д до посинения

}
Re[6]: Множественное наследование
От: IT Россия linq2db.com
Дата: 21.07.04 14:23
Оценка: :))) :))
Здравствуйте, AndrewVK, Вы писали:

IT>>А статейку забульбенить?


AVK>А оно кому нибудь надо? ИМХО в реальности никто этим пользоваться не будет.


Тогда зачем давать такие советы?
... << Rsdn@Home 1.1.4 beta 1 >>
Если нам не помогут, то мы тоже никого не пощадим.
Re[7]: Множественное наследование
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 21.07.04 14:28
Оценка: :)
Здравствуйте, IT, Вы писали:

AVK>>А оно кому нибудь надо? ИМХО в реальности никто этим пользоваться не будет.


IT>Тогда зачем давать такие советы?


Ну дык если очень хочется множественное наследование
... << RSDN@Home 1.1.4 beta 2 >>
AVK Blog
Re[3]: Множественное наследование
От: Dax  
Дата: 21.07.04 16:05
Оценка: 17 (3)
Здравствуйте, Vitaton, Вы писали:

V>В двух словах, как?


1. Вводим декларативный интерфейс With для обозначения интерфейсов, которые будут автоматически подмешены и исходному классу.

// декларировать модмешиваемые интерфейсы можно и аттрибутами, 
// но ввиду известных ограничений generics мы пришли к варианту интерфейсов
interface With<T>{}


2. Для пущей наглядности заводим базовый класс для всех будущих миксинов (для тех, кто встретил новое слово — гуглим по "A Core Calculus of Classes and Mixins. Viviana Bono1, Amit Patel, and Vitaly Shmatikov"):
    class MixinBase<T> {
        protected T Next;

        public MixinBase(T next){    this.Next = next;    }
    }


3. Ввиду статической природы типизации C#, (будем играть по его правилам) декларируем интерфейсы (для того, чтобы было "в двух словах", абсолютно синтетические ):
интерфейс класса, в который будем подмешиваться
    interface IUser    {
        string FirstName{get;set;}
        string LastName{get;set;}
        int? Age;
    }

и интерфейсы, которые будут подмешиваться
    interface IFullNamedUser {
        string FullName { get;set; }
    }
    interface ICryptoNamedUser {
        string CryptoName { get; }
    }


Теперь сами классы...
Главный класс, в который вся наша мешанина будет заливаться
    // т.к. экземпляр наследника этого класса однозначно будет сгенерирован в рантайме, воспользумся генератором,
    // чтобы реализовать абстрактные проперти (генератор можно научить понимать какие-нибудь хинты-атрибуты
    // типа, что делать в случае null value или какие exceptions ловить молча, а какие логировать или выбрасывать наверх
    public abstract class User: IUser, With<FullNameUserMixin>, With<CryptoNameUserMixin> {
        public abstract string FirstName {get;set;} // генератор объявит string fieldFirstName и реализует соотв. get/set
        public abstract string LastName {get;set;} // генератор объявит string fieldLastName и реализует соотв. get/set
        public abstract int? Age {get;set;} // генератор объявит Nullable<int> fieldAge  и реализует соотв. get/set
    }


И синтетический миксины для него:
    // на самом деле миксины могут наследоваться от других миксинов или классов
    // етим и достигается "множественное" наследование (с определенными ограничениями, конечно, но это уже не "в двух словах")
    class FullNameUserMixin: MixinBase<IUser>, IFullNamedUser {

        public FullNameUserMixin(IUser next): base(next){}

        public string FullName {
            get    {    return string.Concat(this.Next.FirstName ?? "DefaultFName", " ", this.Next.LastName ?? "DefaultLName", ", ", this.Age ?? 33);    }
            set    {    string[] n =(value ?? "DefaultFName DefaultLName").Split(' ');    this.Next.FirstName = n[0];    this.Next.LastName = n[1];}
        }

    }
    
    class CryptoNameUserMixin: MixinBase<IUser>, ICryptoNamedUser    {
        MyEncoder encoder;
        string hash;

        public CryptoNameUserMixin(IUser next): base(next) {
            this.encoder = new MyEncoder();
            this.hash = MyRandomHashProvider.GenerateHash();
        }

        public string CryptoName {get { return this.encoder.Encode(this.Next.LastName + this.Next.FirstName + this.hash}}

    }


Теперь использование:
    // MyStaticFab сгенерирует класс, унаследованный от User, реализует его 
    // абстрактные методы и интерфейсы миксинов, указанных в With<T>,
    // добавит для каждого миксина private field и в конструкторе класса
    // проинициализирует их соотв. значениями ( типа, this.someMix = new FullNameUserMixin(this); )
    // обработку методов микс-интерфейсов делегирует соотв. методам this.someMix см ниже реальный код (ImplementTrait)
    User user = MyStaticFab.Generate<User>();
    user.FirstName = "John"; user.LastName = "Smith";
    IFullNamedUser foo = user as IFullNamedUser;
    ICryptoNamedUser bar = user as ICryptoNamedUser;
    Console.WriteLine("FullName is {0}", foo.FullName);
    Console.WriteLine("CryptoName is {0}", bar.CryptoName);



Это метод реально работающего генератора, может, для ясности кому-нить понадобится
        private void ImplementTrait(TypeBuilder tb, ILGenerator cb, Type trait) {
            ILGenerator il = null;

            FieldBuilder fb = tb.DefineField(trait.Name.ToLower(), trait, FieldAttributes.Private | FieldAttributes.InitOnly);

            ConstructorInfo ci = trait.GetConstructors()[0];

            cb.Emit(OpCodes.Ldarg_0); // add code for initializer - this.currentTrait = new CurrentTrait(this);
            cb.Emit(OpCodes.Ldarg_0);
            cb.Emit(OpCodes.Newobj, ci);
            cb.Emit(OpCodes.Stfld, fb);

            foreach(Type iface in trait.GetInterfaces()) { // imp all trait interfaces
                tb.AddInterfaceImplementation(iface);
                foreach(MethodInfo mi in iface.GetMethods()) {
                    ParameterInfo[] pis = mi.GetParameters();
                    Type[] ts = new Type[pis.Length];
                    for(int i=0; i<pis.Length; i++) {
                        ts[i] = pis[i].ParameterType;
                    }
                    MethodBuilder mb = tb.DefineMethod(iface.FullName + "+.+" + mi.Name, MethodAttributes.Private | MethodAttributes.Virtual | MethodAttributes.Final, mi.ReturnType, ts);
                    il = mb.GetILGenerator();
                    il.Emit(OpCodes.Ldarg_0);
                    il.Emit(OpCodes.Ldfld, fb);
                    for(int i=1; i<= pis.Length; i++) {
                        this.EmitLdarg(il, i);
                    }
                    il.Emit(OpCodes.Callvirt, mi);
                    il.Emit(OpCodes.Ret);
                    tb.DefineMethodOverride(mb,mi);
                }
            }

        }
... << silent >>
Re[6]: Множественное наследование
От: Andy77 Ниоткуда  
Дата: 21.07.04 17:31
Оценка:
Здравствуйте, AndrewVK, Вы писали:

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


IT>>А статейку забульбенить?


AVK>А оно кому нибудь надо? ИМХО в реальности никто этим пользоваться не будет.


Надо. А то у самого всё руки не доходят это сделать
Re[7]: Множественное наследование
От: Воронков Василий Россия  
Дата: 21.07.04 18:11
Оценка: :)))
Здравствуйте, IT, Вы писали:

IT>Тогда зачем давать такие советы?


Зачем задавать такие вопросы.
... << Rsdn@Home 1.1.4 beta 1 >>
Re[4]: Множественное наследование
От: foreign Россия http://www.climber.foreign.cd
Дата: 31.08.04 10:51
Оценка:
Здравствуйте, Dax, Вы писали:

Dax>Это метод реально работающего генератора, может, для ясности кому-нить понадобится

Dax>
Dax>        private void ImplementTrait(TypeBuilder tb, ILGenerator cb, Type trait) {
Dax>            ILGenerator il = null;

Dax>            FieldBuilder fb = tb.DefineField(trait.Name.ToLower(), trait, FieldAttributes.Private | FieldAttributes.InitOnly);

Dax>            ConstructorInfo ci = trait.GetConstructors()[0];

Dax>            cb.Emit(OpCodes.Ldarg_0); // add code for initializer - this.currentTrait = new CurrentTrait(this);
Dax>            cb.Emit(OpCodes.Ldarg_0);
Dax>            cb.Emit(OpCodes.Newobj, ci);
Dax>            cb.Emit(OpCodes.Stfld, fb);

Dax>            foreach(Type iface in trait.GetInterfaces()) { // imp all trait interfaces
Dax>                tb.AddInterfaceImplementation(iface);
Dax>                foreach(MethodInfo mi in iface.GetMethods()) {
Dax>                    ParameterInfo[] pis = mi.GetParameters();
Dax>                    Type[] ts = new Type[pis.Length];
Dax>                    for(int i=0; i<pis.Length; i++) {
Dax>                        ts[i] = pis[i].ParameterType;
Dax>                    }
Dax>                    MethodBuilder mb = tb.DefineMethod(iface.FullName + "+.+" + mi.Name, MethodAttributes.Private | MethodAttributes.Virtual | MethodAttributes.Final, mi.ReturnType, ts);
Dax>                    il = mb.GetILGenerator();
Dax>                    il.Emit(OpCodes.Ldarg_0);
Dax>                    il.Emit(OpCodes.Ldfld, fb);
Dax>                    for(int i=1; i<= pis.Length; i++) {
Dax>                        this.EmitLdarg(il, i);
Dax>                    }
Dax>                    il.Emit(OpCodes.Callvirt, mi);
Dax>                    il.Emit(OpCodes.Ret);
Dax>                    tb.DefineMethodOverride(mb,mi);
Dax>                }
Dax>            }

Dax>        }

Dax>


Dax, если не секрет, откуда код?
... << RSDN@Home 1.1.4 beta 2 >>
Re[5]: Множественное наследование
От: Dax  
Дата: 01.09.04 08:10
Оценка:
Здравствуйте, foreign, Вы писали:

F>Dax, если не секрет, откуда код?


Не секрет.
Из моего текущего проекта (название его тебе ничего не скажет).
... << Fastball — The Way >>
Re[7]: Множественное наследование
От: mihailik Украина  
Дата: 01.09.04 11:21
Оценка: -1
S_>Ага. В суровой реальности приходится таким пользоваться.

Вероятнее всего, это не суровая реальность, а суровая ошибка в дизайне

Особенно, если как ты говоришь, "приходится до посинения". Я думаю, финансово наказывать таких архитекторов неправильно, а лучше делать кадровые перестановки.
Re[7]: Множественное наследование
От: mihailik Украина  
Дата: 01.09.04 11:22
Оценка: :)
A>Надо. А то у самого всё руки не доходят это сделать

Видимо, тот случай когда руки дальновиднее головы.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.