Delphi vs C++ vs C#
, ну и Java немножко, где-то ближе к старшему байту номеров страниц
![]() |
Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
|
| ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
| [216.73.216.156] |
|
|
Правила раздела:
| Страницы: (495) « Первая ... 216 217 [218] 219 220 ... 494 495 ( Перейти к последнему сообщению ) |
Delphi vs C++ vs C#
, ну и Java немножко, где-то ближе к старшему байту номеров страниц
|
Сообщ.
#3256
,
|
|
|
|
Цитата korvin @ а что это по-твоему, как не набор полей простой структуры?, не ну можно и просто массив, собственно он от структуры только отсутствием разметки и отличается. В реализации - все, что угодно. Структура + объединение + теги - типичная реализация на С. Иерархия классов - типичная реализации для ОО-языков(scala, nemerle) или в случае библиотечной реализации(попадалась мне статья про такую реализацию для java). Цитата откуда угодно, из сети например Велосипедим все? Читай про стандартные механизмы распределенных вычислений. Контракт он и есть контракт, как он будет задан, и когда будет проверятся - вопрос реализации и особенностей конкретного класса задач. Добавлено Цитата korvin @ Цитата D_KEY @ С тем, который "пришел" На этапе компиляции же. Тип будет выведен, или будет указан явно.откуда пришел? как ты выведешь тип готового объекта неизвестного типа в условиях статической типизации (да и в условиях динамической это не просто)? вот давай я щас опишу какой-нить класс на С++, создам объект и скину тебе его двоичное представление. выведешь тип? причем на этапе компиляции обязательно Можно ближе к реальности? И у двоичного представления спросить поддерживаемые операции будет также непросто |
|
Сообщ.
#3257
,
|
|
|
|
Цитата korvin @ откуда пришел? как ты выведешь тип готового объекта неизвестного типа в условиях статической типизации (да и в условиях динамической это не просто)? вот давай я щас опишу какой-нить класс на С++, создам объект и скину тебе его двоичное представление. выведешь тип? причем на этапе компиляции обязательно а разве при передаче по сети недолжна использоваться сериализация? |
|
Сообщ.
#3258
,
|
|
|
|
Почему же? Если бы у нас был объект неизвестного типа, который по сути не тот что нам нужен, то dynamic_cast<>, в силу своей специфики - возвратил бы нам не просто объект неизвестного типа, а возвратил бы нам 0... |
|
Сообщ.
#3259
,
|
|
|
|
Цитата korvin @ ОМГ. Я понял зачем нужно реал-тайм выведение типа - без этого же нельзя осуществлять сетевой обмен данными. А сериализация, протоколы и прочие велосипеды - это для убогих императивщиков. вот давай я щас опишу какой-нить класс на С++, создам объект и скину тебе его двоичное представление. выведешь тип? причем на этапе компиляции обязательно |
|
Сообщ.
#3260
,
|
|
|
|
Цитата KILLER @ Почему же? Если бы у нас был объект неизвестного типа, который по сути не тот что нам нужен, то dynamic_cast<>, в силу своей специфики - возвратил бы нам не просто объект неизвестного типа, а возвратил бы нам 0... и что нам делать с этим нулем? Добавлено Цитата Adil @ ОМГ. Я понял зачем нужно реал-тайм выведение типа - без этого же нельзя осуществлять сетевой обмен данными. А сериализация, протоколы и прочие велосипеды - это для убогих императивщиков. казалось бы, при чем тут сериализация и убогие императившики Добавлено Цитата Мяут-Настоящий @ а разве при передаче по сети недолжна использоваться сериализация? передаче чего? |
|
Сообщ.
#3261
,
|
|
|
|
Цитата korvin @ Цитата Adil @ ОМГ. Я понял зачем нужно реал-тайм выведение типа - без этого же нельзя осуществлять сетевой обмен данными. А сериализация, протоколы и прочие велосипеды - это для убогих императивщиков. казалось бы, при чем тут сериализация и убогие императившики Но ты так и не объяснил свое желание работать с неизвестными объектами, каким-то магическим образом опрашивая у них поддерживаемые операции. А примеры твои как-то слишком далеки от практики разработки. |
|
Сообщ.
#3262
,
|
|
|
|
Цитата korvin @ и что нам делать с этим нулем? Интересно, а что ты будешь делать с мусором? Добавлено Цитата korvin @ передаче чего? объекта по сети вестимо, ты ведь сам предложил извратный метод, взять потроха объекта неизвестного типа и кинуть по сети... |
|
Сообщ.
#3263
,
|
|
|
|
D_KEY, возвращаясь к баранам, а именно интерфeйсам:
![]() ![]() program IntfImplements; {$APPTYPE CONSOLE} uses SysUtils; type IFoo = interface ['{4135736B-6DFB-4415-B4E7-B652FD586DF4}'] procedure SayFoo; end; IBar = interface ['{E5C7D729-9912-40C8-A7D1-1A378D505E87}'] procedure SayBar; end; TFoo = class abstract (TAggregatedObject, IFoo) protected procedure SayFoo; virtual; abstract; end; TFooA = class(TFoo) protected procedure SayFoo; override; end; TFooB = class(TFoo) protected procedure SayFoo; override; end; TBar = class abstract (TAggregatedObject, IBar) protected procedure SayBar; virtual; abstract; end; TBarM = class(TBar) protected procedure SayBar; override; end; TBarN = class(TBar) protected procedure SayBar; override; end; TBarO = class(TBar) protected procedure SayBar; override; end; TFooKind = (fooA, fooB); TBarKind = (barM, barN, barO); TFooBar = class(TInterfacedObject, IFoo, IBar) strict private FFoo: TFoo; FBar: TBar; protected property Foo: TFoo read FFoo implements IFoo; property Bar: TBar read FBar implements IBar; public constructor Create(FooKind: TFooKind; BarKind: TBarKind); destructor Destroy; override; end; { TFooA } procedure TFooA.SayFoo; begin write('Hello from Foo A'); end; { TFooB } procedure TFooB.SayFoo; begin write('Hello from Foo B'); end; { TBarM } procedure TBarM.SayBar; begin write('Hello from Bar M'); end; { TBarN } procedure TBarN.SayBar; begin write('Hello from Bar N'); end; { TBarO } procedure TBarO.SayBar; begin write('Hello from Bar O'); end; { TFooBar } constructor TFooBar.Create(FooKind: TFooKind; BarKind: TBarKind); begin inherited Create; case FooKind of fooA: FFoo := TFooA.Create(Self); fooB: FFoo := TFooB.Create(Self); else raise Exception.Create('Foo kind unknown'); end; case BarKind of barM: FBar := TBarM.Create(Self); barN: FBar := TBarN.Create(Self); barO: FBar := TBarO.Create(Self); else raise Exception.Create('Bar kind unknown'); end; end; destructor TFooBar.Destroy; begin if assigned(FFoo) then FFoo.Free; if assigned(FBar) then FBar.Free; inherited; end; var FooKind: TFooKind; BarKind: TBarKind; AFoo: IFoo; ABar: IBar; begin ReportMemoryLeaksOnShutdown := True; try for FooKind := fooA to fooB do for BarKind := barM to barO do begin AFoo := TFooBar.Create(FooKind, BarKind); AFoo.SayFoo; write(' and '); ABar := AFoo as IBar; ABar.SayBar; writeln; ABar := nil; end; readln; except on E: Exception do Writeln(E.ClassName, ': ', E.Message); end; end. Это к вопросу о том, что интерфейс - то же самое, что и абстрактный класс... Что сделано: элементарный пример, наследник двух интерфейсов. Для первого - две реализации, для второго - три. Итого возможно 6 сочетаний (2х3). Все варианты создаются динамически, это варианты TFooBar. Вот интересно, а как в С++ это можно сделать через множественное наследование от абстрактных классов? Чтобы не писать NхM вариантов наследования... |
|
Сообщ.
#3264
,
|
|
|
|
Цитата Romkin @ Вот интересно, а как в С++ это можно сделать через множественное наследование от абстрактных классов? Чтобы не писать NхM вариантов наследования... Точно также в TFooBar заводим два объекта, унаследованные от IFoo и IBar и делегируем им методы. Правда делать это нужно вручную. Если поизвращаться, можно автоматизировать. Ты описываешь скорее композицию объектов, а не классов. Если тебе нужна композиция классов, то избавляемся от ужасных(ИМХО) case'ов и делаем через шаблоны. Например, так: ![]() ![]() template<typename FooImpl, typename BarImpl> class TFooBar : public FooImpl, public BarImpl { //... }; И получаем семейство классов, которые будут наследовать реализацию интерфейсов от указанных классов. Реализация в Delphi интересна, но дело не в интерфейсах/абстрактных классах, о в свойствах и делегировании им части реализации класса |
|
Сообщ.
#3265
,
|
|
|
|
Цитата D_KEY @ Реализация в Delphi интересна, но дело не в интерфейсах/абстрактных классах, о в свойствах и делегировании им части реализации класса Видишь ли, написано компактно и довольно "естественно". Что до кейсов - разумеется, это самая простая реализация, я их очень не люблю. Вариантов с фабрикой - полно, и почти таких же простых. Шаблоны писать не так то легко, особенно если есть взаимодействие между делегатами. Тут дело в том, что сделано и без шаблонов, и без явного делегирования методов. И есть второй вариант для интерфейсов: ![]() ![]() type IMyInterface = interface procedure P1; procedure P2; end; TMyClass = class(TObject, IMyInterface) FMyInterface: IMyInterface; property MyInterface: IMyInterface read FMyInterface implements IMyInterface; end; То есть поле уже не класса, а интерфейса. А интерфейс тут может придти откуда угодно, он стандартен. То есть делегирование может быть чисто двоичным и динамическим, плюс не надо иметь сведений даже о размере кокласса. |
|
Сообщ.
#3266
,
|
|
|
|
Romkin, если бы "свойствам" можно было делегировать реализацию не только интерфейсов, но и абстрактных классов, то разницы бы не было. Так что твой пример хорош, но ничего нам не говорит о пользе интерфейсов.
|
|
Сообщ.
#3267
,
|
|
|
|
Цитата D_KEY @ И получаем семейство классов, которые будут наследовать реализацию интерфейсов от указанных классов. общие предки/одноимённые методы/смена реализации в runtime? |
|
Сообщ.
#3268
,
|
|
|
|
Цитата Shaggy @ Цитата D_KEY @ И получаем семейство классов, которые будут наследовать реализацию интерфейсов от указанных классов. общие предки/одноимённые методы/смена реализации в runtime? ![]() Я же говорю, что можно сделать точно также, как в приведенном коде Delphi. Единственная проблема - придется делать руками то, что в Delphi сделано автоматически, но это не связано с интерфейсами. Для автоматизации можно, например, определить операции преобразования типа, возвращающие нужный объект, реализующий интерфейс. Правда это будет не так красиво. |
|
Сообщ.
#3269
,
|
|
|
|
Цитата Qraizer @ Она полностью достаточна и даже больше. Птолемеева система тоже более развита, сколько колец там было на тело? Птолемей сделал два - одно вокруг Земли, и по нему второе, уже с телом. Но говорят, перед Коперником уже до семи доходило. Вот оно, развитие. Это не развитие - это заблуждение, но речь не об этом... Цитата Qraizer @ то покажи, пожалуйста. Это искусственный пример из некой темы. Класс SS производный от S, каждый имеет по указателю на int. Требуется обеспечить строгую гарантию, т.е. отсутствие утечек ресурсов и утери предыдущего состояния при любых ошибках. Интерфейсный объект естественно будет больше. К слову, а в случае исключения будут вызываться деструкторы объектов на стеке (не обвёрнутых в try-catch)? Цитата Qraizer @ Суждения не из-за этого, суждения с ваших же слов. О монолитности, о неявлении себя базовым классом при наследовании, о полном контроле базовых классов производным, о вмешательстве базовых классов в дела производных итп. Сведений более чем достаточно. Сами по себе виртуальные конст... сама по себе виртуальная инициализация после конструирования вещь иногда полезная, а говнокод ...да, ваш хороший код обязан с нашей точки зрения быть говнокодом в таких условиях, иначе он просто небезопасен. И что ты понял из наших слов? О "монолитности"? О "неявлении себя базовым классом при наследовании"? О "о полном контроле базовых классов производным"? О "вмешательстве базовых классов в дела производных"? Но речь то совсем не о них Добавлено Цитата D_KEY @ А зачем тогда вообще работать с динамическими объектами? |
|
Сообщ.
#3270
,
|
|
|
|
Цитата DesweR @ О "монолитности"? О монолитности, вы говорите уже со 150-той страницы, если не ошибаюсь, усердно доказывая что это круто! Цитата DesweR @ Но речь то совсем не о них Ты б пояснил, подведя итоги, я ведь просил раскрыть тему. А ты все пустые слова на ветер кидаешь. Цитата DesweR @ А зачем тогда вообще работать с динамическими объектами? А что, объекты расположеные в динамической области памяти по определению неизвестные? |