Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 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
1-1288366250
Vasena
2010-10-29 19:30
2012.03.11
Полиморфизм+"множественное наследование"


15-1321821005
Юрий
2011-11-21 00:30
2012.03.11
С днем рождения ! 21 ноября 2011 понедельник


2-1322594941
Jacksotnik
2011-11-29 23:29
2012.03.11
Помогите с отчетом


15-1321469110
wl
2011-11-16 22:45
2012.03.11
На хабрахабре открыта регистрация


6-1253185020
bvv
2009-09-17 14:57
2012.03.11
Проблема с потоками сканирования





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский