Ru-Board.club
← Вернуться в раздел «Прикладное программирование»

» Вопросы по Embarcadero RAD Studio XE4

Автор: Eternal_Shield
Дата сообщения: 17.06.2013 09:46
HeMet

Цитата:
Нужно использовать TDictionary<string, T>.

Врят ли найдётся человек, который будет использовать TStringList.AddObject('a', Pointer($1)) вне известных компонентов (TMemo, TCombobox и т.п)
Автор: Arioch1
Дата сообщения: 17.06.2013 11:16

Цитата:
почем нельзя "достать" из объекта, который поддерживает IChild родительский интерфейс IParent?


diamond problem


Код: IParent=interface
end;

ISon=interface(IParent)
end;

IDaughter=interface(IParent)
end;


TChild=class(TInterfacedObject, ISon,IDaughter);

i_parent := IParent(TChild.Create); // which one ???
Автор: ego666
Дата сообщения: 17.06.2013 11:19

Цитата:
Еще раз - TList<T> невозможно расширить так, чтобы изменить поведение - в этом имхо убогость его архитектуры.

Убогость в твоей логической цепочке. Ещё раз: TList выполняет ровно то, что в него заложено, но если бы он вообще был ни на что негоден, то тогда можно было бы говорить о убогости.


Цитата:
На Win это обсуловлено спецификой поддержки COM. И непонятно чем это обсуловлено на OSX/iOS

Тем, что интерфейсы в Delphi придерживаются идеологии COM, не конкретной платформозависимой фичей MS, а именно её идеологии.


Цитата:
Мне такое поведение кажется нелогичным

http://forum.ru-board.com/topic.cgi?forum=33&topic=13680&start=357&limit=1&m=1#1

Добавлено:

Цитата:
diamond problem

Интересно, а в джаве/шарпе что будет с аналогичным кодом? У них же интерфейсы наследуются.
Автор: deks
Дата сообщения: 17.06.2013 11:25
Arioch1

Ну - какой интерфейс IParent реализуется объектом TChild, такой и доставать!

Не забываем, что проблема "ромбовидного" наследования характерна именно для множественного наследования полноценных объектов, то есть там, где есть РЕАЛИЗАЦИЯ методов базового класса, которая может быть различна у потомков.

А вот интерфейс - это как бы АБСТРАКТНЫЙ класс, без реализации.

Поэтому все упрощается: в указанном примере все будет ок, вся неоднозначность должна быть снята при реализации TChild, мы просто укажем явно как именно реализовывать IParent.

Добавлено:
ego666


Цитата:
Убогость в твоей логической цепочке. Ещё раз: TList выполняет ровно то, что в него заложено, но если бы он вообще был ни на что негоден, то тогда можно было бы говорить о убогости.


Убогость в том, что TList мог бы выполнять гораздо больше путем простой метки "virtual" у методов. Причем, причины отсутствия этой метки не ясны. И убогость в том, что он может выполнять ТОЛЬКО ТО что в него заложено, а изменить поведение не получится. Если тебе кажется что менять поведение стандартных контейнеров нет смысла - ну и живи с этим чувством! Я ж не спорю с твоим мироощущением - ты имеешь на него полное право. Видимо, по существу означенной проблемы ты возразить не можешь: TList не может менять свое поведение.

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

Еще раз: есть задача изменить поведение TList. Подробнее: есть реализованный на его базе список файлов в каталоге. Список с отложенным чтением самого каталога (чтобы объект создавался быстро), но по доступу, например к свойству Count этот список читается. Вопрос: как реализовать это на TList?

Мой ответ: никак! По непонятной причине методы TList не виртуальные, нужно делать собственную реализацию. У этого подхода огромный недостаток - для любых посторонних объектов, которые умеют работать с TList, собственная реализация не подходит!
Автор: Eternal_Shield
Дата сообщения: 17.06.2013 11:53
Arioch1

Цитата:
а когда дженериков не было ?

В случае с компонентами, конкретно я всегда создавал DummyObject с необходимыми мне полями и всё, либо соотв. дин. массив.

Тут, конечно, другой гемор появлялся, но чтобы Pointer(43) пихать в AddObject ... было пару раз по молодости.

Автор: ego666
Дата сообщения: 17.06.2013 12:00
[more]
Цитата:
Причем, причины отсутствия этой метки не ясны

TList<T> это калька с обычного TList, почему обычный TList так спроектировали? Как отвечают в армии - потому что в общем вот.


Цитата:
Если тебе кажется что менять поведение стандартных контейнеров нет смысла - ну и живи с этим чувством!

В 99% случаев мне стандартного поведения хватает с головой, ну а если мне хочется странного - я просто подключаю стороннюю библиотеку, а не истерю на весть форум почему разработчики RTL такие негодники и чего то там для меня не предусмотрели, да соглашусь, что это было бы удобно, но это не фатально, можно либо взять готовое, либо написать своё. Дальнейшее обсуждение архитектуры TList считаю бессмысленным.


Цитата:
Поэтому все упрощается:  в указанном примере все будет ок, вся неоднозначность должна быть снята при реализации TChild, мы просто укажем явно как именно реализовывать IParent. 

А каким образом можно явно указывать как реализовывать IParent, если он явно не указан в классе? Откуда вообще можно узнать какой у ISon и IDaughter родитель?

Зато в Delphi есть TStream, с которым можно реализовать действительно что угодно - вот это реально полезная и используемая вещь.

А вот что действительно попадает под категорию убогость архитектуры - так это отсутствие у остальных языков виртуальных конструкторов, отсутствие классовых конструкторов, классовых деструкторов, классовых методов, статичных классовых методов (у остальных языков есть только последний). [/more]

Добавлено:
P.S.
А можно как-нибудь писать длинные посты без сворачивания?
Автор: Eternal_Shield
Дата сообщения: 17.06.2013 13:21
ego666

Цитата:
Интересно, а в джаве/шарпе что будет с аналогичным кодом? У них же интерфейсы наследуются.

Это-сэто, а что, в C#/Java есть понятие интерфейса, а не, тупо, класса? Разумеется, что в C# аналогичный код работает, ибо "интерфейс" всего лишь абстрактный класс. Нету в этих языках понятия интерфейс, имхо.
Автор: deks
Дата сообщения: 17.06.2013 15:12
Eternal_Shield

Хм. А чем дельфовый интерфейс концептуально отличается от абстрактного класса? Ну, кроме возможности реализовать много интерфейсов одним классом?
Автор: valgreesh
Дата сообщения: 17.06.2013 15:42
Arioch1

Цитата:
Другими словами интеропа - нет, он не обеспечен ни проблемно, ни тем более беспроблемно (но есть теоретическая возможность его обеспечить и COM VTBL этому как-то поможет)

Интероп с win32 обеспечен таки беспроблемный (для буквоедов добавлю - при условии использования ограниченного количества типов и прочее бла-бла) (мы можем получить интерфейс извне и использовать его привычным образом - Direct2D, например. Мы можем отдать интерфейс во вне и его смогут использовать). Что же касается Objective-C... Чем являются тамошние протоколы, если не абстрактными классами из C++ -> интерфейсами?
Автор: AlekXL
Дата сообщения: 17.06.2013 16:17

Цитата:
Еще раз - TList<T> невозможно расширить так, чтобы изменить поведение - в этом имхо убогость его архитектуры. В .NET/Java/ObjC можно менять поведение, а в Дельфи нет
ну брось. Это всего лишь вариант реализации. Юзай Delphi.Collections. Там все есть.


Добавлено:
Я вот понять не могу.. Если я пишу код для ios, и подключаю внешнюю нестандартную(скажем,C++) библиотеку, то как это все может работать в эмуляторе, если эмулятор работает по x86, а устройство - на ARM?
Мне что, нужно два варианта библиотеки? И получается, отлаживать 1-в-1 можно только подключив ios устройство?
И еще вопрос. В лазаре вообще нет отладчика для ios, или андроида?
Автор: deks
Дата сообщения: 17.06.2013 18:01
AlekXL


Цитата:
Юзай Delphi.Collections

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


Цитата:
как это все может работать в эмуляторе


Для эмулятора все компилируется для x86, для устройства - в armv7, armv7s. И приложение, и библиотеки. И да, без устройства отладить приложение не получится - производительность эмулятора в x86 и arm на устройстве может ОЧЕНЬ СИЛЬНО отличаться. К тому же на эмуляторе есть/были ограничения в поддерживаемых фичах (Game Center, iCloud, etc).
Автор: Arioch1
Дата сообщения: 17.06.2013 18:46

Цитата:
Интероп с win32 обеспечен таки беспроблемный

причем еще в Delphi 2.0


Цитата:
Что же касается Objective-C... Чем являются тамошние протоколы

Не знаю и знать не хочу
Мне обещали УЖЕ реализованное БЕСПРОБЛЕМНОЕ взаимодействие на уровне базовый для языков строительных блоков - объектов

Добавлено:

Цитата:
А чем дельфовый интерфейс концептуально отличается от абстрактного класса?

Например явным запретом на наследование и поддержкой нескольких парраллельно существующих интерфейсов одной сущностью (I1.Count и i2.Count при этом совсем разные методы)


Цитата:
Поэтому все упрощается:  в указанном примере все будет ок, вся неоднозначность должна быть снята при реализации TChild, мы просто укажем явно как именно реализовывать IParent.  


Это разумеется. Можно сделать класс, поддерживающий и IParent и IChild, их обоих.
Но вопрос-то был - http://forum.ru-board.com/topic.cgi?forum=33&topic=13680&start=340#19 - именно почему так нужно делать, почему IParent не появляется автоматически, при указании IChild
Автор: Eternal_Shield
Дата сообщения: 17.06.2013 20:18
deks

Цитата:
Хм. А чем дельфовый интерфейс концептуально отличается от абстрактного класса? Ну, кроме возможности реализовать много интерфейсов одним классом?

Я бы не стал называть интерфейс абстрактным классом. Мало общего начиная с низу и кончая верхом ))

[more]Я воспринимаю интерфейсы как нечто самостоятельное.[/more]

В С++ же общее всё от и до. В С# тоже самое, стоит лишь поиграться с наследованием и видно, что поведение одинаковое с классами. Думаю, что и layout 100% одинаковый. [more]Хорошо одно: MS везде проверки понатыкала от нубов. Более менее на делфийские интерфейсы похожи, даль только наследование разное, отсюда несовместимость ... или я ошибаюсь? поправьте [/more]

Автор: valgreesh
Дата сообщения: 17.06.2013 22:11
Arioch1

Цитата:
причем еще в Delphi 2.0

Ценное замечание, особенно если учесть, что речь об интерфейсах...


Цитата:
Мне обещали УЖЕ реализованное БЕСПРОБЛЕМНОЕ взаимодействие на уровне базовый для языков строительных блоков - объектов

Никто таких глупостей не обещал.
Автор: ego666
Дата сообщения: 18.06.2013 04:32

Цитата:
именно почему так нужно делать, почему IParent не появляется автоматически, при указании IChild

не тупи, с предыдущей страницы вам уже два раза объясняли.

Вот пример как это может вылезти боком:

Добавлено:
[more]
Код: IList = interface
function GetItem: T;
procedure SetItem(Item: T);
end;

TList = class(TInterfacedObject, IList)
private
function GetItem: T;
procedure SetItem(Item: T);
end;

...

var
List: IList;
begin
List := TList.Create;

//юзаем методы интерфейса IList
List.SetItem(...);
... := List.GetItem;
end;
Автор: Arioch1
Дата сообщения: 18.06.2013 07:36

Цитата:
Ценное замечание, особенно если учесть, что речь об интерфейсах...

Не совсем, речь о том, что якобы интерфейсы обеспечили возможность использования win32


Цитата:
Никто таких глупостей не обещал.


Цитата:
обеспечивается беспроблемный интероп с ... Objective C ... кодом


Автор: Eternal_Shield
Дата сообщения: 18.06.2013 10:44
ego666

Цитата:
Вот пример как это может вылезти боком:

Интересно, что этот пример демонстрирует? Почему TFileList не унаследован от TList? Тогда будут доступны интерфейсы IList и IFileList из TFileList и не надо будет реализовывать дополнительно методы IList в TFileList

Да и с каких это пор родитель (в вашем случае IList) обязан знать, что добавлено в наследниках (IFileList) и, главное, по какому такому святому правилу? Вот это уже реальным бредом пахнет, а не то, что Вам пытался донести deks с проблемами TList<>, но как об стенку горохом
Автор: ego666
Дата сообщения: 18.06.2013 11:09

Цитата:
Почему TFileList не унаследован от TList?

С какой стати? Первый - это массив элементов. Второй - допустим список строк в файле. Внутренняя реализация этих классов совершенно разная.


Цитата:
Тогда будут доступны интерфейсы IList и IFileList из TFileList

Ты наверное не понял, ещё посмотри раз код, мне как раз и нужно чтобы интерфейса IList не было в TFileList, т.к. сам по себе IList без методов Open и Close (как в IFileList) бесполезен и опасен.


Цитата:
и не надо будет реализовывать дополнительно методы IList в TFileList

Мне не это нужно. Понимаешь, это интерфейс а не класс, в IFileList от IList наследуется интерфейс, а не реализация, в TList и TFileList интерфейсы будут реализованы по разному, целиком и полностью по разному.

Добавлено:

Цитата:
Да и с каких это пор родитель (в вашем случае IList) обязан знать, что добавлено в наследниках (IFileList) и, главное, по какому такому святому правилу?

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

Ещё раз повторю, ты просто не понял кода (и возможно зачем вообще нужны интерфейсы).
Автор: Eternal_Shield
Дата сообщения: 18.06.2013 11:45
ego666

Цитата:
Ещё раз повторю, ты просто не понял кода (и возможно зачем вообще нужны интерфейсы).

Я отлично понял, как эта логика работает. Подробности реализации меня не интересуют. Достаточно было сказать:

Цитата:
Мне не это нужно. Понимаешь, это интерфейс а не класс, в IFileList от IList наследуется интерфейс, а не реализация, в TList и TFileList интерфейсы будут реализованы по разному, целиком и полностью по разному.

и на этом остановиться, а не изображать из меня идиота. Делать мне нечего, как гадать на кофейной гуще на тему "чего там под капотом".


Цитата:
А он и не знает и не должен знать, потому что он абстрактный интерфейс, он может как угодно быть реализован, от него можно как угодно унаследоваться и потом этого наследника можно тоже как угодно реализовать и эта реализация может на сколько угодно отличаться от реализации родителя, потому что это интерфейсы, такова их идеология (двигаемая COM'ом).

А мы не путаем IUnknown и IDispatch? Формализуйте понятие "абстрактный интерфейс" ...
Автор: ego666
Дата сообщения: 18.06.2013 12:07

Цитата:
и на этом остановиться, а не изображать из меня идиота

извиняюсь

Добавлено:

Цитата:
А мы не путаем IUnknown и IDispatch

это вообще из другой оперы.


Цитата:
Формализуйте понятие "абстрактный интерфейс"

COM рекомендует писать интерфейсы с неопределённым смыслом (с простым/обобщённым/универсальным наименованием методов), чтобы каждая отдельная реализация этого интерфейса могла его, "смысл" интерфейса, интерпретировать по своему.
Автор: deks
Дата сообщения: 18.06.2013 12:44
Eternal_Shield

Цитата:
Нету в этих языках понятия интерфейс, имхо.


Хм. Тогда переспрошу - а чем принципиально отличаются интерфейсы C#/Java от Delphi?
Автор: Eternal_Shield
Дата сообщения: 18.06.2013 14:07
ego666

Цитата:
это вообще из другой оперы.

Не IDispatch ли решает подобную проблему .. по типу той, что в примере? ...


Цитата:
COM рекомендует писать интерфейсы с неопределённым смыслом (с простым/обобщённым/универсальным наименованием методов), чтобы каждая отдельная реализация этого интерфейса могла его, "смысл" интерфейса, интерпретировать по своему.

Верно, 1 интерфейс - N реализаций ... и как сие попадает под определение, что родитель должен знать о всех методах всех своих наследников? В постулатах COM о таких отношениях/обязанностях ни слова.

В нашем случае, как IList может знать о методах в своих наследниках IFileFile, IStreamList и т.п.? С какого перепугу vtbl родителя изменится, чтобы отразить методы его наследников? ...

deks

Цитата:
Хм. Тогда переспрошу - а чем принципиально отличаются интерфейсы C#/Java от Delphi?

Тем, как происходит наследование. Сие различие портит восхитительный интероп между C# приложением и Delphi DLL в нашем чудном проекте

Это относится к C#, а не Java.
Автор: deks
Дата сообщения: 18.06.2013 14:38
Eternal_Shield


Цитата:
Тем, как происходит наследование


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

Пример старый:
Код:
IParent=interface
procedure P1;
end;

IChild=interface(IParent)
procedure P2;
end;

TChild=class(IChild)
procedure P1;
procedure P2;
end;

var
i_parent: IParent;
i_child: IChild;
chld: TChild;
begin
chld := new TChild;

i_child := chld; // (1) OK
i_parent := chld; // (2)
i_parent := i_child; // (3)

i_parent.P1;

i_child.P1;
i_child.P2;
end;
Автор: AlekXL
Дата сообщения: 18.06.2013 16:31

Цитата:
WTF! - нелогично же.

ну вообще, Diamond проблема и впрямь может нарисоваться(в Win32):

Код:
program Project24;

{$APPTYPE CONSOLE}

{$R *.res}

uses
System.SysUtils;
type
IChild=interface
function PreferDolls():boolean;
end;

IBoy=interface(IChild)

end;

IGirl=interface(IChild)

end;

TBoy=class(TInterfacedObject,IBoy)
function PreferDolls():boolean;
end;


THermAphrodite=class(TInterfacedObject,IBoy,IGirl)
strict protected
FBoy:IBoy;
property Boy:IBoy read FBoy implements IBoy;
procedure AfterConstruction();override;
public
function PreferDolls_g():boolean;
function IGirl.PreferDolls=PreferDolls_g;

end;


{ THermAphrodite }

procedure THermAphrodite.AfterConstruction;
begin
inherited;
FBoy:=TBoy.Create();
end;

function THermAphrodite.PreferDolls_g: boolean;
begin
result:=true;//girl
end;


{ TBoy }

function TBoy.PreferDolls: boolean;
begin
result:=false;//boy
end;

var i_chld:IChild;
herm:THermAphrodite;

begin
try
{ TODO -oUser -cConsole Main : Insert code here }
herm:=THermAphrodite.Create();
i_chld:= IBoy( herm );
writeln('Prefer dolls(IChild from IBoy)',i_chld.PreferDolls);
i_chld:= IGirl( herm );
writeln('Prefer dolls(IChild from IGirl)',i_chld.PreferDolls);


except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.

Автор: deks
Дата сообщения: 18.06.2013 16:57
AlekXL

А в чем проблема? При неоднозначности - требовать уточнять какой именно интерфейс доставать! Типа IChild(IBoy()) или IChild(IGirl()). Компилятор то знает обо всех этих неоднозначностях. При этом - неоднозначность легко убирается путем уточнения (в существующем примере так и делается). А вот возможности достать из объекта родительский интерфейс при отсутствии неоднозначностей почему-то нету!

upd: Имхо, класс THermAphrodite проще и понятнее записать так
Код:

THermAphrodite=class(TInterfacedObject,IBoy,IGirl)
public
function PreferDolls_Yes: Boolean; // for girls
function PreferDolls_No: Boolean; // for boys

function IGirl.PreferDolls = PreferDolls_Yes;
function IBoy.PreferDolls = PreferDolls_No;
end;
Автор: Eternal_Shield
Дата сообщения: 18.06.2013 17:02
deks

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

Меня, пока что, не напрягает

Автор: AlekXL
Дата сообщения: 18.06.2013 17:08

Цитата:
А в чем проблема? При неоднозначности - требовать уточнять какой именно интерфейс доставать! Типа IChild(IBoy()) или IChild(IGirl()). Компилятор то знает обо всех этих неоднозначностях. При этом - неоднозначность легко убирается путем уточнения (в существующем примере так и делается).
проблема в том, что Delphi - это все-таки не C++. Есть у Delphi пределы компетентности. Хотите блекджек и остальное - юзайте C++ Builder!

А еще - есть ленивые программисты, которые не хотят ворошить компилятор без крайней нужды. (Впрочем, неудивительно . Даже один из кодеров FPC высказывал свое ФЭ по поводу синтаксиса анонимов в Delphi - мол сложно реализовать парсер)

И, судя по всему - исходники компилятора Delphi внутри - это гадюшник, клубок змей, где лучше ни к чему не прикасаться.


Добавлено:

Цитата:
upd: Имхо, класс THermAphrodite проще и понятнее записать так

нет. Гермафродит - редко такое случается. А интерфейсы IBoy и IGirl - это обычное дело. И этих интефейсах может быть не один, а СТО один метод, реализовывать которые заново - это трудоемко и неправитьно.

Лучше унаследовать THermaphordite скажем, от уже готовой реализации TGirl(IGirl) - и сделать агрегацию c TBoy.
К сожалению, эта вкусняшка встречается лишь в Win компиляторе. Я ведь уже упоминал ленивых программистов?
Автор: deks
Дата сообщения: 18.06.2013 17:28
AlekXL

Ну - мы то тут про конкретный пример к diamond problem (оно же "ромбовидное наследование"). А про способы, как в классе делать поддержку интерфейсов - да, есть куча удобных техник. И использование наследования (берем реализацию из класс-родителя), и делегирование реализации специальному member.
Автор: valgreesh
Дата сообщения: 18.06.2013 17:35
Arioch1

Цитата:
речь о том, что якобы интерфейсы обеспечили возможность использования win32

Вау! Вот это фантазия... Воистину, каждый видит что хочет )


Цитата:
обеспечивается беспроблемный интероп с ... Objective C ... кодом

В фигурном цитировании упражняешься? Ок, но без меня.
Автор: Arioch1
Дата сообщения: 18.06.2013 18:36

Цитата:
компилятор ошибку ловит (не хватает реализации IPArent.P1).

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

Добавлено:

Цитата:
В фигурном цитировании упражняешься


Вырезанное сделала утверждение менее сильным, полное утверждение потребовало бы еще и C++ кроме ObjC

Добавлено:

Цитата:
или мы не сможем достать родительский интерфейс из объекта!

Ибо его там нет.

Мне иногда кажется, что главный глюу с интерфейсами был в GUID.
С одной стороны сказали, что тоьлко GUIDные интерфейсы поддерживают type safety, is & as
С другой стороны не запретили интерфейсы без GUIDа

В результате и получается то так то этак.

"Наследование" интерфейсов имеет не больше смысле, чем наследование record'ов и кроме удобства декларации в нём ничего не должно было бы быть.

Страницы: 1234567891011121314151617181920212223242526

Предыдущая тема: cxDBPivotGrid выгрузка в excel


Форум Ru-Board.club — поднят 15-09-2016 числа. Цель - сохранить наследие старого Ru-Board, истории становления российского интернета. Сделано для людей.