Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2003.05.12;
Скачать: [xml.tar.bz2];

Вниз

Проблемы с полиморфизмом с ребенком в другом Package   Найти похожие ветки 

 
NightDaro   (2003-04-28 00:14) [0]

Здравствуйте.
Такая проблема:
Рассмотрим классовую иерархию:
-- в модуле Base.Pas --
TClass1 = class(TComponent);
-- в модуле Son.Pas, во внешнем пакете Plugin.bpl --
TClass2 = class (TClass1);
-- в Main.pas, загружается Plugin.bpl,
TForm1.Create:
var obj : TClass1;
lst : TComponentList;
...
obj := TClass1(GetClass("TClass2")).Create(Self);
lst.Add(obj);
(lst[0] as TClass1).CallMethod;
^^^^^^^^^^
В этой строке при выполнении оператор as генерит исключение TInvalidTypeCast. То есть не может преобразовать объект класса TClass2 к типу TClass1.

Просьба прокомментировать эту ситуацию, или предложить другие подходы к решению проблемы (Базовое приложение общается с plugin"ами через полиморфизм, основное приложение и plugin"ы uses Base, а потом - описанное выше).
Спасибо.


 
Goffman   (2003-04-28 06:10) [1]


> obj := TClass1(GetClass("TClass2")).Create(Self);

Наверно правильно будет
obj := TClass1(GetClass("TClass2").Create(Self));
Дело в том, что ты пытаешься привести классовую переменную к объектной.

зы: надеюсь ничего не перепутал


 
NightDaro   (2003-04-28 09:32) [2]

Почему тогда в Obj все нормально присваивается?


 
Goffman   (2003-04-28 09:59) [3]

Как это нормально присваивается?
Функция GetClass возвращает объект типа class of TPersistent
Ты его пытаешься привести к классу TClass1, который, грубо говоря, находится в совсем другой иерархической ветке.
Такая попытка неизменно должна привести к AV (что у меня и происходит).
Ты наверное чегой-то не договариваешь.
Если хочешь пришли исходник(bruhno@mail.ru)


 
REA   (2003-04-28 10:39) [4]

Класс зарегистрирован?


 
er   (2003-04-28 10:48) [5]

Попробуй так:

TClass1Class = class of TClass1;

obj := TClass1Class(GetClass("TClass2").Create(Self));


 
REA   (2003-04-28 10:49) [6]

А надо ли вообще приведение типа в данном случае? Компилятор ругается? Я вообще делал списки метаклассов.


 
er   (2003-04-28 11:05) [7]

REA © (28.04.03 10:49)
Надо.
По крайней мере, к TComponentClass - поскольку
конструктор с AOwner"ом введён именно там.



 
NightDaro   (2003-04-28 11:27) [8]

Sorry, я так и писал с самого начала:

TClass1Class = class of TClass1;
...
obj := TClass1Class(GetClass("TClass2")).Create;

Писать GetClass("...").Create(Self) нельзя, тк Er объяснил. Проблема в том, что операторы is и as потом глючат. Но если написать TClass1(lst[0]).CallMethod, то все будет работать. Вот это и непонятно. В чем тогда отличие работы as и приведения типов?



 
REA   (2003-04-28 11:38) [9]

Ну и приводить тогда к TComponentClass.
На то он и plugin чтобы делать некоторую абстракцию.
Упоминание правда имени класса в явном виде тоже непонятно зачем.
Зарегистрировать наверно все-же надо. Иначе GetClass не найдет ничего.


 
NightDaro   (2003-04-28 11:49) [10]

Все регистрирую. А в явном виде TClass1 применяю, чтобы с десяток функций через GetInterface не доставать, а потом еще из них список интерфейсов не делать и с каждым объектом хранить.. А теперь представим, что у вас архитектура из 7 ортогональных иерархий plugin"ов и они между собой взаимодействуют..
Короче, у меня все работает через приведение типов. а as - не работает.


 
REA   (2003-04-28 11:53) [11]

А as применим к метаклассам?
Я имел ввиду упоминание TClass2 в явном виде, что убирает абстракцию.


 
NightDaro   (2003-04-28 12:01) [12]

У меня пакет пассивный - только классы регистрирует. Их список получается через конфигурационный файл, они сортируются там по типам, а потом из них плагины типа Manager набирают себе детей. так что не знаю как можно убрать TClass2.
На счет применимости - не знаю. В Help-е мало слишком написанно, непонятно, а опыта пока нет (Теперь, можно сказать, есть:).


 
Goffman   (2003-04-28 12:05) [13]

Оператор as - это и есть оператор приведения типов.
В чем его смысл
1. Если ты сделаешь так:
TForm(lst[0]).Name:="rrr";
то delphi это проглотит.
2 .(lst[0] as TForm).Name:="rrr";
-> Invalid typeCast

В чем ошибка, я понять не могу. Я промоделировал у себя твою ситуацию. Все работает нормально, что с as что с прямым приведением типов.

Вот код если интересно
unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs;

type
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
TClass1 = class(TComponent);
TClass2 = class (TClass1);
TClass1Class = class of TClass1;

var
Form1: TForm1;

implementation

uses Contnrs;

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
var obj : TClass1;
lst : TComponentList;
begin
lst:=TComponentList.Create;
obj := TClass1Class(GetClass("TClass2")).Create(Self);
lst.Add(obj);
(lst[0] as TClass1).Name:="rrr";
end;

initialization
RegisterClass(TClass1);
RegisterClass(TClass2);
end.


 
NightDaro   (2003-04-28 12:10) [14]

:) Спасибо, Goffman, у меня все абсолютно замечательно работало, пока я оставался в рамках одого EXE-шника. Попробуй теперь сделать package, в нем файл Unit2.pas uses Unit1.pas, TClass2=class(TClass1), в нем RegisterClass(TClass2);
Потом: в главном модуле - LoadPackage, потом - все то же самое.
Просьба сообщить, если заработает, значит я какую-нибудь мелочь пропустил..


 
Goffman   (2003-04-28 12:56) [15]

Дошло :)
Смотри:
Есть модуль (условно Unit1), в котором объявлен TClass1.
Этот модуль подключается и к основному проекту и к плагину.
В итоге что получается: При загрузке пакета Unit1 будет присутствовать в двух экземплярах. То есть в приложении будет два совершенно разных с точки зрения среды выполнения класса TClass1.
В пакете TClass2 будет наследиком одного TClass1, а в основном модуле ты его приводишь к другому TClass1, отсюда и инвалид.

Что нужно сделать.
Вынести описание TClass1 в отдельный пакет, и скомпилировать приложение и твой плагин с этим пакетом


 
NightDaro   (2003-04-28 20:10) [16]

Кошмар. Спасибо, объяснили!



Страницы: 1 вся ветка

Форум: "Основная";
Текущий архив: 2003.05.12;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.49 MB
Время: 0.009 c
14-34582
Nick-From
2003-04-23 18:38
2003.05.12
Нужен курсовик по СЦОС


3-34370
geg
2003-04-22 13:27
2003.05.12
DBgid+Подсчет строк?


14-34554
Спрашивающий
2003-04-23 07:34
2003.05.12
Русская справка по сообщениям Win


4-34659
devol
2003-03-11 09:44
2003.05.12
Hook клавиатуре


1-34488
Tihas
2003-04-29 16:29
2003.05.12
Вопросик на тему вызова сишных функций из dll





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский