Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2012.03.11;
Скачать: CL | DM;

Вниз

Полиморфизм+"множественное наследование"   Найти похожие ветки 

 
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;
Скачать: CL | DM;

Наверх




Память: 0.51 MB
Время: 0.008 c
2-1322567877
Gu
2011-11-29 15:57
2012.03.11
длина пароля из политик


15-1321561802
Юрий
2011-11-18 00:30
2012.03.11
С днем рождения ! 18 ноября 2011 пятница


15-1321122840
Максим
2011-11-12 22:34
2012.03.11
Что делать в случае если Windows уже не помещается на винте?


15-1321309685
Дмитрий С
2011-11-15 02:28
2012.03.11
Не понимаю, зачем википедия постоянно попрошайничает.


3-1272650997
YanKl
2010-04-30 22:09
2012.03.11
bde,paradox. Связь одной таблицы с двумя родительскими