Форум: "Основная";
Текущий архив: 2012.03.11;
Скачать: [xml.tar.bz2];
ВнизПолиморфизм+"множественное наследование" Найти похожие ветки
← →
Vasena © (2010-10-29 19:30) [0]Есть набор классов и интерфейса:
type
IEncoding = interface
procedure SetEncoding(NewEncoding: byte);
function GetEncoding: byte;
end;
TFrameData = class(TInterfacedObject)
[...]
end;
TTextFrameData = class(TFrameData, IEncoding)
private
Encoding: byte;
[...]
public
procedure SetEncoding(NewEncoding: byte); inline;
function GetEncoding: byte; inline;
[...]
end;
Есть массив обектов:var
TestArray: array of TFrameData;
В массиве находятся объекты !наследуемых! от TFrameData класса (т.е. объеткы TTextFrameData)TestArray[i]:=TTextFrameData.Create();
Хочу сделать такую вещь, но как я не пытаюсь типы привести ничего не получается:var
Encoding: IEncoding;
begin
[...]
Encoding:=TestArray[i]; // ошибка здесь
if Encoding.GetEncoding > $01 then
Encoding.SetEncoding($01);
[...]
end;
Посоветуйте как сделать чтобы задумка работала???
PS Delphi 2010
← →
Игорь Шевченко © (2010-10-29 20:02) [1]
> // ошибка здесь
секретная очевидно.
1. Не надо работать с наследниками TInterfacedObject, как с классами, надо как с интерфейсами, и наче ждет немало граблей.
2. TInterfaceList спасет от всех бед.
← →
Vasena © (2010-10-29 20:12) [2]
> секретная очевидно.
> пытаюсь типы привести ничего не получается
> 2. TInterfaceList спасет от всех бед.
я так понял предлагаете заменить массив на спивок, если да, но это не вариант, да и собственно суть ошибки не в этом...
> 1. Не надо работать с наследниками TInterfacedObject, как
> с классами, надо как с интерфейсами, и наче ждет немало
> граблей.
не совсем понял что имеется ввиду...
PS суть проблемы: есть ссылки на базовый тип, но хранятся объекты наследники, базовый тип не реализует нужный интерфейс, а вот наследники - да, как правильно вызвать методы интерфейса, через ссылку на базовый класс (наследуемых классов много, в примере - один...)
← →
_Юрий (2010-10-29 20:17) [3]if supports(TestArray[i], IEncoding, Encoding) then
← →
Vasena © (2010-10-29 20:28) [4]Юрий, спасибо, всё заработало, за одно и ошибку нашел (оказалось интерфейсу нужно было GUID указать еще...)
← →
Игорь Шевченко © (2010-10-29 23:53) [5]
> PS суть проблемы: есть ссылки на базовый тип, но хранятся
> объекты наследники, базовый тип не реализует нужный интерфейс,
> а вот наследники - да, как правильно вызвать методы интерфейса,
> через ссылку на базовый класс (наследуемых классов много,
> в примере - один...)
Надо нанять программиста
← →
_Юрий (2010-10-30 11:17) [6]
> Надо нанять программиста
Программисты никогда не проверяют TObject на поддержку интерфейса? Может быть, не нужно ерундой болтать?
← →
Vasena © (2010-10-30 15:29) [7]хм все замечательно, однако после вызова метода объявленного в интерфейсе, у классов очищаются private поля (только String), с чем это может быть связано???
← →
Palladin © (2010-11-01 15:52) [8]космические лучи
← →
reonid © (2010-11-02 18:10) [9]Работать с интерфейсами в таком стиле
(используя их главным образом как объекты)
в принципе можно, но для этого нужно
во-первых, запретить подсчет ссылок. Например, сделать собственный
базовый класс, подобный TInterfacedObject:function TRInterfacedObject._AddRef: Integer; stdcall;
begin
Result := -1;
end;
function TRInterfacedObject._Release: Integer; stdcall;
begin
Result := -1;
end;
function TRInterfacedObject.QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
const E_NOINTERFACE = HResult($80004002);
begin
if GetInterface(IID, Obj) then
Result := 0
else
Result := E_NOINTERFACE;
end;
в противном случае можно получить неожиданное разрушение объекта
в процессе работы с ним через интерфейс.
Во-вторых, использовать ссылки на интерфейс только в локальных переменных. (Т.е. никаких списков интерфейсов. Это другой подход).
Желательно сделать функции-оболочки для доступа к
функциональности интерфейса, наподобие
function GetEncoding(Obj: TObject; var Encoding: Byte): Boolean;
var enc: IEncoding;
begin
Result := False;
//Encoding := DefaultValue; //??
if Supports(Obj, IEncoding, enc) then
begin
Result := True;
Encoding := enc.GetEncoding;
end;
end;
и нигде, кроме таких функций, переменные типа IEncoding не объявлять.
Везде использовать только ссылки на объекты.
Иначе можно получить интерфейсную ссылку на уже уничтоженный объект.
← →
Юрий Зотов © (2010-11-02 18:31) [10]
> reonid © (02.11.10 18:10) [9]
> Работать с интерфейсами в таком стиле
> (используя их главным образом как объекты)
> в принципе можно, но для этого нужно
Лень, я бы сказал немного иначе:
Работать с интерфейсами как с объектами в принципе можно, но НЕ нужно. Чтобы не искать приключений.
← →
DiamondShark © (2010-11-02 18:54) [11]
> Vasena © (30.10.10 15:29) [7]
> хм все замечательно, однако после вызова метода объявленного
> в интерфейсе, у классов очищаются private поля (только String),
> с чем это может быть связано???
> 1. Не надо работать с наследниками TInterfacedObject, как
> с классами, надо как с интерфейсами, и наче ждет немало
> граблей.
После освобождения всех интерфейсных ссылок экземпляр удаляется (и финализируется).
← →
reonid © (2010-11-02 19:31) [12]>Юрий Зотов © (02.11.10 18:31) [10]
>Работать с интерфейсами как с объектами в принципе можно, но НЕ нужно.
>Чтобы не искать приключений.
Да вобщем, иногда бывает нужно. (Я сам грешен :-))) )
Собственно, это бывает нужно, когда реализуешь
библиотеку и в ней хочется минимизировать интерфейс объектов,
не засоряя базовые классы необязательными операциями.
А опциональные операции удобно вынести в подмешиваемые интерфейсы.
И предоставить объектам на выбор,
какой интерфейс из поддерживаемых некоторым обобщенным
алгоритмом реализовать. Или не реализовывать ни одного
и довольствоваться дефолтным поведением.
Конкретно я использовал такой подход в только библиотеке
векторной графики. Возможно, всё это можно было реализовать
и по другому. Но сожалеть о таком подходе я пока повода не имел...
← →
Vasena © (2010-11-03 23:36) [13]Спасибо reonid проблема действительно была в ссылках, написав свой TInterfacedObject всё заработало
Ps функции доступа писать оказалось не нужно ибо доступ в программе через интерфейс организован точно также как у вас в функции описано
PPS Всем спасибо за помощь, проблема решена
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2012.03.11;
Скачать: [xml.tar.bz2];
Память: 0.49 MB
Время: 0.003 c