Форум: "Основная";
Текущий архив: 2002.09.26;
Скачать: [xml.tar.bz2];
ВнизВспомнить все. Или есть ли у компилятара память. Найти похожие ветки
← →
id_privin (2002-09-14 13:52) [0]Такие вот грабли. Есть два модуля Unit1 просто форма проекта, и Unit2 тут зарыты грабли.
unit Unit2;
interface
uses ComObj,Dialogs,Classes;
type
ParentI = interface
procedure FuckYou; <<
end;
ChildI = interface(ParentI)
procedure WOW;
end;
ChildImpl = class(TInterfacedObject,ChildI)
procedure FuckYou; <<
procedure WOW;
end;
TParent = class(TInterfacedObject,ParentI)
protected
I : ParentI;
public
property A : ParentI read I implements ParentI;
end;
TChild = class(TParent)
public
constructor Create;
end;
implementation
procedure ChildImpl.FuckYou; <<
begin <<
MessageDlg("Fuck You", mtWarning, [], 0); <<
end; <<
procedure ChildImpl.WOW;
begin
MessageDlg("WOW", mtInformation, [mbOK], 0);
end;
constructor TChild.Create;
begin
inherited Create;
I := ParentI(ChildI(ChildImpl.Create));
end;
end.
===========
unit Unit1;
interface
uses
Forms, Classes, Controls, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
end;
var
Form1: TForm1;
implementation
uses Unit2;
{$R *.DFM}
procedure TForm1.Button1Click(Sender: TObject);
var
P : TParent;
begin
P := TChild.Create;
ChildI(ParentI(P)).WOW; <<<ГРАБЛИ ТУТ >>>
P.Free;
end;
end.
Так вот, если все писать по порядку т.е. сначала Unit2 а потом процедуру в Unit1 то на месте граблей компилятор говорит
Internal Error E 1289
Тогда делаю так, в Unit2 убираю все что связанно с процедурой FuckYou(сторочки помечены << ). Компилирую - все ок. Вставляю строчки обратно - все ок. В том месте где грабли ставлю вместо WOW FuckYou - опять E1289. Снова убираю строки из Unit2. Получаю сообщение что идентификатор не определенн. Вставляю строки. Компилирую - все ок.
Вопросы. Лечиться ли это? У меня ли одного такие грабли? Может я просто тормоз, и чего то делаю не так как задумал Inprise;
← →
Fog (2002-09-14 13:59) [1]Может не надо ругаться на компилятор, и он не заметит :)
← →
drpass (2002-09-14 15:34) [2]Подозреваю, что такой программный изврат авторам компилятора просто и присниться не мог
← →
Immortal Deach (2002-09-14 21:42) [3]да, скорее, это не ты сильно мудрый, а компил. сильно тебя не понимающий....
← →
id_privin (2002-09-16 10:35) [4]Эти неврахумительные посты, - это все что могут сказать мастаки?
Тогда поставим вопрос по другому,
Есть ли еще варианты реализации шаблонов в Delphi?
← →
Separator (2002-09-16 10:46) [5]Попробуй удалить *.dcu и по новой откомпилировать
← →
Shaman_Naydak (2002-09-16 11:24) [6]Родной, сделай так:
После ParentI = interface
и до процедуры вставь строчку и нажми Shift-Ctrl-G, чтобы сгенерировать гуид. Аналогичную операцию проверни у наследуемого интерфейса, и пребудет с тобой счастье.
Ты ж гуиды не задал, и компилятор физически не может отличить интерфейсы..
Пошли дальше.. Настоятельно не рекомендую использовать
явное приведение типов с интерфейсами.. Это идея больна на голову.
Например, вместо
ChildI(ParentI(P)).WOW; <<<ГРАБЛИ ТУТ >>>
лучше сделать так: (P as ChildI).WOW;
Удачи в нелегких извратах
← →
id_privin (2002-09-16 12:01) [7]Вау спасибо, действительно ГУИД надо писать, а я думал это только Com"у нужно.
А вот второй совет не работает если писать P as ChildI то в run time будет Interface not Supported. Если оставить как есть будет Internal erorror. А вот ((P as ParentI) as ChildI) работает.
Насколько я теперь понял as c интерфейсами работает только если есть GUID? да?
← →
id_privin (2002-09-16 12:11) [8]хмм. В тестовом проекте все зароботало, но вот в настоящем, все по прежнему. Несмотря на GUID оператор as не работает. При двойном приведении по прежнему Internal error. Может дело в том что интерфейсы объявлены в пакетах, причем в разных?
← →
Shaman_Naydak (2002-09-16 13:07) [9]да, все интерфейсы надо снабжать guid"aми..
Так как все сводится к QueryInterface, а он без гуида как-то не работает..
Ты прав. Только ((P as ParentI) as ChildI) даст требуемый результат.
Но хочу обратить твое внимание на распространенную ошибку, возникающую при смешивании объектного и интерфейсного подхода:
procedure TForm1.Button1Click(Sender: TObject);
var
P: TParent;
begin
P:=TChild.Create;
((P as ParentI) as ChildI).WOW; // после этой строчки объект уже будет автоматически освобожден
P.Free; // тут ты уже второй раз освобождаешь этот же объект
end;
Наилучшим способом решения этого затруднения является использование только интерфейсной модели:
procedure TForm1.Button1Click(Sender: TObject);
var
P: ParentI;
begin
P:=TChild.Create;
(P as ChildI).WOW;
end;
Объект автоматически уничтожится при выходе из области видимости..
Пойдем дальше, или вернее смотрим еще выше:
ChildImpl = class(TInterfacedObject,ChildI)
procedure FuckYou;
procedure WOW;
end;
Так как ты рассчитываешь работать с ним не через СhildI, а через ParentI, то было бы правильнее определить так:
ChildImpl = class(TInterfacedObject, ParentI, ChildI)
procedure FuckYou;
procedure WOW;
end;
Никаких дополнительных усилий для реализации родительского интерфейса, само-собой, не требуется..
И следующая строка тоже примет человеческий вид:
constructor TChild.Create;
begin
inherited Create;
// I := ParentI(ChildI(ChildImpl.Create));
I:=ChildImpl.Create;
end;
Нет, пакеты влиять не должны.. Где-то ошибка.. Ищи.
Если не справишься, кинь письмом, гляну.
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2002.09.26;
Скачать: [xml.tar.bz2];
Память: 0.47 MB
Время: 0.009 c