Зачем?
От: Аноним  
Дата: 06.10.05 08:43
Оценка: 11 (3) +3
По мне так не зачем, а почему. Неспособность реализовать множественного наследования при данной архитектуре выдали за преимущество. Если, что я не пытаюсь доказать, что множественно наследование крайне необходимо и без него жить нельзя.

P.S. Гради Буч:
Необходимость множественного наследования в OOP остается предметом горячих споров. По нашему опыту, множественное наследование — как парашют: как правило, он не нужен, но, когда вдруг он понадобится, будет жаль, если его не окажется под рукой.
-----
Нулевое оформления постов благодаря Opere.


данное сообщение получено с www.gotdotnet.ru
ссылка на оригинальное сообщение
Re: Зачем?
От: hugo Австрия  
Дата: 06.10.05 07:44
Оценка: 9 (2)
Здравствуйте, Аноним, Вы писали:

А>в с++ разрешено множестенное наследование

А>в с# — нет.

А>объясняется тем что помогает избежать многих ошибок но что то этих ошибок я представить не могу.

А>но я уверен что если множестевнное наследование запретили в c# значит ошибки были действиетльно важные и избежать из было трудно.

Я бы еще добавил, что множественное наследование — это white-box reuse, т.е. известна реализация базового класса (следовательно появляется зависимость). При множественном же наследовании интерфейсов для реализации можно использовать композицию объектов, т.н. black-box reuse (нет зависимости от реализации).
Второе с точки зрения проектирования более правильно, поскольку первое нарушает инкапсуляцию.
Re[5]: Зачем?
От: Аноним  
Дата: 06.10.05 08:21
Оценка: 5 (1) :)
Ну — не совсем. Тут проблема посерьезнее.
Беда в том, что в с++ приходится быть крепким задним умом — проблема возникнет бог знает когда и бог знает у кого и в каком коде, а виртуальное наследование нужно уже сейчас. А как быть с библиотечными классами?

Единственное реальное решение — это вводить механизм явного управления веткой наследования каждого виртуального метода и (вполне вероятно, я не силен в теории) каждого member-а, причем не только у непосредственных предков, но и у всей иерархии.

Dll-hell возникает только если что-то делать не так, не соблюдать простых правил. А тут hell обеспечен в любом случае.

Так что тут уже что в лоб, что по лбу. Что вводить неимоверно сложный механизм управления в язык, что оставить его простым, а программистам предложить pattern с агрегацией — и пусть выкручиваются как хотят. Кстати, есть вспомогательный tool-ы для этого дела.

Хотя я (ей-богу) предпочел бы язык с множественным наследованием, но урезанным. Скажем, ввести помимо struct-ов еще понятие mixin-а и разрешить класам иметь только одного предка не-mixin-а и сколько угодно mixin-ов. Ну а для последних и ввести нужный набор ограничений/механизмов. А еще очень бы хотелось новенькую губозакатывательную машинку.
Re: Зачем?
От: Аноним  
Дата: 06.10.05 07:14
Оценка: -2
abstract class CBase
{
protected int _i;

public abstract void DoIt();
}

class C1 : CBase
{
public virtual void DoIt()
{
_i = 1;
}
}

class C2 : CBase
{
public virtual void DoIt()
{
_i = 2;
}
}

class C3: C1, C2
{
public void Do()
{
DoIt();
Console.Write(i); // ???
}
}
Re[5]: Зачем?
От: Andrbig  
Дата: 06.10.05 08:17
Оценка: +1 :)
Здравствуйте, Аноним, Вы писали:

А>зы: но хотелось бы посмотреть на зверя типа class

А>MyUserControl : DataGridView, ListView

Сложно быть паровозом и велосипедом одновременно.
Re[2]: Зачем?
От: Аноним  
Дата: 07.10.05 07:55
Оценка: 1 (1)
Вот именно. А как раз в этом CLS и нету МН именно по вопросам совместимости.
-----------------------
Вы действительно считаете что МН в CLS нету ради совместимости с VB в котором МН не было и нету?
-----
Нулевое оформления постов благодаря Opere.


данное сообщение получено с www.gotdotnet.ru
ссылка на оригинальное сообщение
Re: Зачем?
От: GlebZ Россия  
Дата: 07.10.05 10:50
Оценка: 1 (1)
Здравствуйте, Аноним, Вы писали:

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

public class A
{
int _a;
public A(int a)
{
_a=1;
}
virtual void Init(){_a+=1;}
}

public class B
{
int _b;
public B()
{
Init();
}
virtual void Init(){_b=1;}
}

public class C:A,B
{
public C(int i):base(i)
{
}
override void Init(){base.Init();}
}

С с=new C(1);

Здесь сразу же несколько ошибок. Если компилятор такое пропустит, то вообще не локализуешь ошибку. Но допустим компилятор дает ошибки на подобную ситуацию.
А теперь представь что класс A находится в другой сборке. При компиляции объекта С — у него отсутствовала функция Init. То есть, конфликта как такового нету. Потом сборку с объектом A перекомпилили, и добавили метод Init.
Для концептуально-выверенного языка, который построен для того чтобы уменьшать ошибки программистов такие выпендрежи делать нельзя. Проблемы решить можно. Пуская даже криво, но можно. Вобщем, кроме заметного усложнения, особых плюсов не получишь. А это не может быть совместимо с идеалогией C# и CLS.

С уважением, Gleb.
Зачем?
От: Аноним  
Дата: 06.10.05 06:54
Оценка: +1
в с++ разрешено множестенное наследование
в с# — нет.

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



10.10.05 11:05: Перенесено из '.NET'
Re[2]: Зачем?
От: Аноним  
Дата: 06.10.05 07:33
Оценка: +1
Здравствуйте, Аноним, Вы писали:

А>abstract class CBase

А>{
А>protected int _i;

А>public abstract void DoIt();

А>}

А>class C1 : CBase

А>{
А>public virtual void DoIt()
А>{
А>_i = 1;
А>}
А>}

А>class C2 : CBase

А>{
А>public virtual void DoIt()
А>{
А>_i = 2;
А>}
А>}

А>class C3: C1, C2

А>{
А>public void Do()
А>{
А> DoIt();
А> Console.Write(i); // ???
А>}
А>}


1. мне кажется не i а _i
2. _i ты и не увидишь даже из С3
3. а если даже и наследовать так:

class C1 : public CBase
class C2 : public CBase


то почему бы и не обращаться по полному квалификационному имени?
типа

class C3: C1, C2
{
 public void Do()
 {
   С1::DoIt();
   Console.Write(C1::_i);
 }
}


зы: а если ты имел ввиду вызов неизвестного DoIt()

class C3: C1, C2
{
 public void Do()
 {
   DoIt();
   Console.Write(i); // ???
 }
}


такое вообще скомпилиться?
если да то плохо, но в любом случае надо указывать С1::DoIt(); или С2::DoIt();
или с таким явным указанием тоже есть какие то проблемы?
Re[5]: Зачем?
От: DenisCh Россия  
Дата: 06.10.05 11:53
Оценка: :)
Здравствуйте, <Аноним>, Вы писали:


А>>>vb# — a это кто?

DC>>VB.NET
А>ну ты ж так и пешы

Это ж на 4 символа длиннее!
... << RSDN@Home 1.1.4 stable rev. 510>>
Re[3]: Зачем?
От: Аноним  
Дата: 06.10.05 07:47
Оценка:
А>1. мне кажется не i а _i
Ну да, очепятка.
А>2. _i ты и не увидишь даже из С3
? В этом и суть.
А>то почему бы и не обращаться по полному квалификационному имени?
...
А>или с таким явным указанием тоже есть какие то проблемы?
Ну конечно, есть. Клиент, который обо всех этих сложностях не подозревал, просто вызывал c3.DoIt. Куда деваться бедному крестьянину?
A>такое вообще скомпилиться?
Код имеет такую тенденцию — меняться со временем.

Факт остается фактом, даже при наличии понятия виртуального наследования с++ имеет с этим проблемы. Они носят скорее практический, чем теоретический характер.
В системах с общим базовым предком у всех классов ситуация становится просто невыносимой. Собственно, ни одна такая система (из известных мне) ее и не вынесла.
Насколько я помню, даже mfc и managed c++ этим отличаются.
Re[4]: Зачем?
От: Аноним  
Дата: 06.10.05 08:05
Оценка:
Здравствуйте, Аноним, Вы писали:

А>>1. мне кажется не i а _i

А>Ну да, очепятка.
А>>2. _i ты и не увидишь даже из С3
А>? В этом и суть.
А>>то почему бы и не обращаться по полному квалификационному имени?
А>...
А>>или с таким явным указанием тоже есть какие то проблемы?
А>Ну конечно, есть. Клиент, который обо всех этих сложностях не подозревал, просто вызывал c3.DoIt. Куда деваться бедному крестьянину?
A>>такое вообще скомпилиться?
А>Код имеет такую тенденцию — меняться со временем.

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

А>В системах с общим базовым предком у всех классов ситуация становится просто невыносимой. Собственно, ни одна такая система (из известных мне) ее и не вынесла.
А>Насколько я помню, даже mfc и managed c++ этим отличаются.

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

а вообщем я согласен что проблем после запрета множественного наследования меньше.

один предок и куча интерфесов — все же удобно

зы: но хотелось бы посмотреть на зверя типа class
MyUserControl : DataGridView, ListView
Re[6]: Зачем?
От: Аноним  
Дата: 06.10.05 08:28
Оценка:
Здравствуйте, Andrbig, Вы писали:

A>Здравствуйте, Аноним, Вы писали:


А>>зы: но хотелось бы посмотреть на зверя типа class

А>>MyUserControl : DataGridView, ListView

A>Сложно быть паровозом и велосипедом одновременно.


а в с++ еще и можно
Re: Зачем?
От: DenisCh Россия  
Дата: 06.10.05 08:43
Оценка:
Здравствуйте, <Аноним>, Вы писали:

А>в с++ разрешено множестенное наследование

А>в с# — нет.
А>объясняется тем что помогает избежать многих ошибок но что то этих ошибок я представить не могу.
А>но я уверен что если множестевнное наследование запретили в c# значит ошибки были действиетльно важные и избежать из было трудно.

Объясняется тем, что c# компилирует в MSIL. Туда же компилируют и VB#, и другие. А в этих других _нет_ множественного наследования. А для использования C#-класса в VB#-классе они жолжны быть совместимы. Вон есть managedC++. попробуй на нём сделать множественное наследование...
... << RSDN@Home 1.1.4 stable rev. 510>>
Re[2]: Зачем?
От: Аноним  
Дата: 06.10.05 08:48
Оценка:
Здравствуйте, DenisCh, Вы писали:

DC>Здравствуйте, <Аноним>, Вы писали:


А>>в с++ разрешено множестенное наследование

А>>в с# — нет.
А>>объясняется тем что помогает избежать многих ошибок но что то этих ошибок я представить не могу.
А>>но я уверен что если множестевнное наследование запретили в c# значит ошибки были действиетльно важные и избежать из было трудно.

DC>Объясняется тем, что c# компилирует в MSIL. Туда же компилируют и VB#, и другие. А в этих других _нет_ множественного наследования. А для использования C#-класса в VB#-классе они жолжны быть совместимы. Вон есть managedC++. попробуй на нём сделать множественное наследование...


vb# — a это кто?
Re[3]: Зачем?
От: DenisCh Россия  
Дата: 06.10.05 09:00
Оценка:
Здравствуйте, <Аноним>, Вы писали:

А>vb# — a это кто?


VB.NET
... << RSDN@Home 1.1.4 stable rev. 510>>
Re[4]: Зачем?
От: Аноним  
Дата: 06.10.05 09:14
Оценка:
Здравствуйте, DenisCh, Вы писали:

DC>Здравствуйте, <Аноним>, Вы писали:


А>>vb# — a это кто?


DC>VB.NET


ну ты ж так и пешы
Re[6]: Зачем?
От: Аноним  
Дата: 06.10.05 12:41
Оценка:
Здравствуйте, DenisCh, Вы писали:

DC>Здравствуйте, <Аноним>, Вы писали:



А>>>>vb# — a это кто?

DC>>>VB.NET
А>>ну ты ж так и пешы

DC>Это ж на 4 символа длиннее!


так нету такого языка как VB#
Re: Зачем?
От: Аноним  
Дата: 06.10.05 13:43
Оценка:
По своим функциональным возможностям языки могут как угодно отличаться друг от друга, а для обеспечения совместимости существует Common Language Specification (CLS).



данное сообщение получено с www.gotdotnet.ru
ссылка на оригинальное сообщение
Re[2]: Зачем?
От: Timeo  
Дата: 06.10.05 13:52
Оценка:
Здравствуйте, DenisCh, Вы писали:

А>>в с++ разрешено множестенное наследование

А>>в с# — нет.
А>>объясняется тем что помогает избежать многих ошибок но что то этих ошибок я представить не могу.
А>>но я уверен что если множестевнное наследование запретили в c# значит ошибки были действиетльно важные и избежать из было трудно.

DC>Объясняется тем, что c# компилирует в MSIL. Туда же компилируют и VB#, и другие. А в этих других _нет_ множественного наследования. А для использования C#-класса в VB#-классе они жолжны быть совместимы. Вон есть managedC++. попробуй на нём сделать множественное наследование...


Это не аргумент. VB# создавался для .Net, отличия от старого VB afaik очень значительные. Т.е. в VB# нет множественного наследования из-за того, что множественного наследования нет в .Net.
Re[5]: Зачем?
От: Timeo  
Дата: 06.10.05 15:00
Оценка:
Здравствуйте, Аноним, Вы писали:

А>а вообщем я согласен что проблем после запрета множественного наследования меньше.

А>один предок и куча интерфесов — все же удобно
А>зы: но хотелось бы посмотреть на зверя типа class
А>MyUserControl : DataGridView, ListView

А вот звери типа CMyControl : LWindow, LListener, LController очень даже существуют и неплохо применяются.
Кстати, использование интерфейсов — это тоже своего рода множественное наследование. Только урезанное.
Re[2]: Зачем?
От: DenisCh Россия  
Дата: 07.10.05 06:19
Оценка:
Здравствуйте, shadowmaan1, Вы писали:

S>По своим функциональным возможностям языки могут как угодно отличаться друг от друга, а для обеспечения совместимости существует Common Language Specification (CLS).


Вот именно. А как раз в этом CLS и нету МН именно по вопросам совместимости.
... << RSDN@Home 1.1.4 stable rev. 510>>
Re[2]: Зачем?
От: GlebZ Россия  
Дата: 07.10.05 10:46
Оценка:
Здравствуйте, DenisCh, Вы писали:

DC>Объясняется тем, что c# компилирует в MSIL. Туда же компилируют и VB#, и другие. А в этих других _нет_ множественного наследования. А для использования C#-класса в VB#-классе они жолжны быть совместимы. Вон есть managedC++. попробуй на нём сделать множественное наследование...

C++/CLI — на здоровье. И работает. Для MSIL — множественное наследование не проблема. Это проблема CLS.

С уважением, Gleb.
Re[3]: Зачем?
От: Sinclair Россия https://github.com/evilguest/
Дата: 07.10.05 14:10
Оценка:
Здравствуйте, GlebZ, Вы писали:

GZ>C++/CLI — на здоровье. И работает. Для MSIL — множественное наследование не проблема. Это проблема CLS.

Хм. Лично мне казалось, что невозможно в терминах MSIL написать такой класс, объекты которого бы успешно кастилисм к двум различным классам.
Имхо, все реализации MI в Net суть хаки. И компилер либо прячет такие классы от публики, либо выпрямляет иерархию, либо еще как утаптывает это все в стандартные рамки.
... << RSDN@Home 1.1.4 stable rev. 510>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[4]: Зачем?
От: GlebZ Россия  
Дата: 07.10.05 19:07
Оценка:
Здравствуйте, Sinclair, Вы писали:

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


GZ>>C++/CLI — на здоровье. И работает. Для MSIL — множественное наследование не проблема. Это проблема CLS.

S>Хм. Лично мне казалось, что невозможно в терминах MSIL написать такой класс, объекты которого бы успешно кастилисм к двум различным классам.
S>Имхо, все реализации MI в Net суть хаки. И компилер либо прячет такие классы от публики, либо выпрямляет иерархию, либо еще как утаптывает это все в стандартные рамки.
Это не только твое, присоединяюсь. Основные проблемы в метаданных. Ну не держат они множественное наследование. Из-за этого, там такая пурга творится, что мама не балуйся. Но на этапе компиляции никаких проблем нет. JIT мало понимает кто перед ним — метод интерфейса или метод объекта. Он это узнает по метаданным. И получается такая фигня, для интерфейсов, которые поддерживают множественное наследование он генерит следующий код(заглядывать в ассемблер сейчас не буду, да и к тому-же для многих непонятно будет).
Для MSIL такая конструкция callvirt instance bla-bla которая в случае множественного наследования без дебаггинга на ассемблер вываливается в таком виде
1. у this из виртуальной таблицы — взять указатель на виртульную таблицы конкретного интерфейса
2. взять указатель из виртуальной таблицы интерфейса указатель на функцию
3. выполнить
То есть система абсолютно аналогична unmanaged C++. Код практически всегда оптимизируется JIT до прямых вызовов. Это действительно только для неоптимизированного дебуга.(11.4.1.4 Virtual Calling Convention)
То есть компиляция при множественном наследовании есть. Она в принципе стандартна(если не говорить об оптимизациях).
Мало того, я не нашел в спецификации, где бы говорилось что callvirt опознает c кем он работает, с интерфейсом или объектом.

В спецификации(сейчас у меня только 1.1) нашел только такой интересный параграф.

callvirt, part of the CIL common type system instruction set, uses the class of an object (known only at runtime) to determine the method to be called. The instruction includes a method reference, but the particular method isn’t computed until the call actually occurs. This allows an instance of a subclass to be supplied and the method appropriate for that subclass to be invoked. The callvirt instruction is used both for instance methods and methods on interfaces. For further details, see the Common Type System specification and the CIL Instruction Set specification.


Так что хаком можно попробовать сделать множественное наследование с несколькими виртуальными таблицами. Пока времени нет.

С уважением, Gleb.

ЗЫ:Оказалось в ref классах действительно нет наследования. Для остальных злостная эмуляция.
Re[5]: Зачем?
От: Sinclair Россия https://github.com/evilguest/
Дата: 07.10.05 19:21
Оценка:
Здравствуйте, GlebZ, Вы писали:
GZ>Это не только твое, присоединяюсь. Основные проблемы в метаданных. Ну не держат они множественное наследование. Из-за этого, там такая пурга творится, что мама не балуйся. Но на этапе компиляции никаких проблем нет. JIT мало понимает кто перед ним — метод интерфейса или метод объекта. Он это узнает по метаданным. И получается такая фигня, для интерфейсов, которые поддерживают множественное наследование он генерит следующий код(заглядывать в ассемблер сейчас не буду, да и к тому-же для многих непонятно будет).
GZ>Для MSIL такая конструкция callvirt instance bla-bla которая в случае множественного наследования без дебаггинга на ассемблер вываливается в таком виде
GZ>1. у this из виртуальной таблицы — взять указатель на виртульную таблицы конкретного интерфейса
GZ>2. взять указатель из виртуальной таблицы интерфейса указатель на функцию
GZ>3. выполнить
GZ>То есть система абсолютно аналогична unmanaged C++.
Не, тут проблема вовсе не в callvirt. Проблема в castclass. Не будет она работать с такими псевдоклассами. А с интерфейсами — будет.
... << RSDN@Home 1.1.4 stable rev. 510>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[3]: Зачем?
От: DenisCh Россия  
Дата: 10.10.05 05:05
Оценка:
Здравствуйте, AndroidLV, Вы писали:

ALV>Вот именно. А как раз в этом CLS и нету МН именно по вопросам совместимости.

ALV>Вы действительно считаете что МН в CLS нету ради совместимости с VB в котором МН не было и нету?

Это не я так считаю. Это я прочитал в одной из книжек (какой — не помню).
... << RSDN@Home 1.1.4 stable rev. 510>>
Re[2]: Зачем?
От: Mr. None Россия http://mrnone.blogspot.com
Дата: 10.10.05 07:39
Оценка:
Здравствуйте, Аноним, Вы писали:

Если вы имели в виду C++, то будет так

А>class CBase

А>{
А>protected int _i;

А>public: virtual void DoIt() = 0;

А>}

А>class C1 : public CBase

А>{
А>public: virtual void DoIt()
А>{
А>_i = 1;
А>}
А>}

А>class C2 : public CBase

А>{
А>public: virtual void DoIt()
А>{
А>_i = 2;
А>}
А>}

А>class C3: public C1, public C2

А>{
А>public void Do()
А>{
А> DoIt();
error C2385: ambiguous access of 'DoIt' in 'C3'
А> Console.Write(i); // ???
А>}
А>}

Поэтому в случае C++ никакой проблемы нет.
Собственно нет её и в самом множественном наследовании. А почему его нет в C# — элементарно Ватсон... В C# все классы наследуются от одного базовго класса (Object), если разрешить множественное наследование, то оно всегда будет "брильянтовым" и при такой иерархии обращение к любому методу этого класса (например, ToString) либо придётся снабжать явным квалификатором доступа (что не удобно), либо всё наследование делать виртуальными (что возможно накладно)... В MS поступили проще — запретили множественное наследование...
Почему было не сделать виртуальным только наследование от класса Object и только в случае иерархии с множественным наследованием, я не знаю. Если к этому ещё добавить автоматическую генерацию и замещение всех методов класса Object в новом классе, то никакой проблемы бы не было... Очевидно не сделали по той же причине, по которой объекты by-value гарантировано уничтожаются при выходе за пределы локальной области вызова, но при этом у них отсутсвует деструктор... Либо не успевали, либо не додумались, либо это очень сильно не ложилось в общую архитектуру системы, что решили не исправлять... Вобщем сделали не как удобно, а как велел отдел маркетинга.
Компьютер сделает всё, что вы ему скажете, но это может сильно отличаться от того, что вы имели в виду.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.