Модераторы: Poseidon, Snowy, bems, MetalFan

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Проверить принадлежность классу, сложная ситуация 
:(
    Опции темы
Delphist
  Дата 10.1.2011, 01:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Delphist Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2145
Регистрация: 3.2.2004
Где: всегда в сети

Репутация: 2
Всего: 3



Возник вопрос по определению принадлежности объекта к классу, а именно, есть класс:
Код

type
  TRawClass = class(TObject)
   public
      Owner: TCustomClass;
      procedure Method;
  end
  TCustomClass = class(TObject)
  public
     RawClass: TRawClass; 

     constructor Create;
  end;

type
   TFirstClass = class(TCustomClass)
     ...
   end;

   TSecondClass = class(TCustomClass)
     ...
   end;
   
   TThirdClass = class(TSecondClass)
     ...
   end;
constructor TCustomClass.Create;
begin

  inherited;
  RawClass  := TRawClass.Create(Self);
end


Как я должен написать в методе TRawClass.Method, чтобы узнать, что Owner является ли класс TSecondClass или классом унаследованных от TSecondClass (т.е. TThirdClass)
Код

procedure TRawClass.Method;
begin
   
  if Owner is TSecondClass  then //это не помогает
   ...
  //делал так:
  if Owner.InheristForm(TSecondClass) then //тоже не помогает
   ...
 //делал так:
  if Owner.ClassType = TSecondClass then // срабатывает только для TSecondClass, а для наследника TThirdClass уже нет
   ...
end;


Это сообщение отредактировал(а) Delphist - 10.1.2011, 01:22


--------------------
ProcessInfo 1-ая моя программа (аналог spyxx.exe с гораздо большим функц-ом - внедрение dll в адр. простр. процесса, перехват API-функций, разбор приложения на окна мн.др).
Когда-то давным-давно использовал это...
PM MAIL ICQ   Вверх
mes
Дата 10.1.2011, 01:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 1
Всего: 250



см. as 


--------------------
PM MAIL WWW   Вверх
БелАмор
Дата 10.1.2011, 09:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 209
Регистрация: 10.6.2010
Где: Россия

Репутация: 5
Всего: 17



Код

unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    Button1: TButton;
    SpeedButton1: TSpeedButton;
    BitBtn1: TBitBtn;
    procedure AnyButtonClick(Sender: TObject);  // Назначить всем кнопкам
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}                      

procedure TForm1.AnyButtonClick(Sender: TObject);
const
  sTButton = 'TButton';
begin
  if Sender.ClassName = 'TSpeedButton' then
    ShowMessage('Это - TSpeedButton');

  if Sender.ClassNameIs(sTButton) then
    ShowMessage('Это - TButton');

  if Sender.ClassNameIs(TBitBtn.ClassName) then
    ShowMessage('Это - TBitBtn');
end;

end.

PM   Вверх
БелАмор
Дата 10.1.2011, 10:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 209
Регистрация: 10.6.2010
Где: Россия

Репутация: 5
Всего: 17



is проверяет принадлежность объекта классу или его наследнику, в большинстве случаев этого достаточно. Если нужно отсечь наследников и проверять на точное соответствие, то картина усложняется.
Надёжным вариантом является проверка имени класса, получаемого через метод ClassName, либо проверка напрямую через метод IsClassName. Для того, чтобы не допустить опечаток, можно использовать именованные константы, либо получать имя класса через классовый метод напрямую из нужного класса, что и было продемонстрировано в приведённом коде.
Мне было лень это писать, но один голос с оценкой -3 вынудил сделать это.
Хотелось бы, чтобы поставивший -3 сделал ответную любезность и обосновал свою позицию.
PM   Вверх
superVad
Дата 10.1.2011, 10:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 735
Регистрация: 6.4.2006
Где: Черкассы, Украина

Репутация: 4
Всего: 15



БелАмор, не напрягайся smile, вон автора топика в прошлой теме вообще в ноль заминусовали.

Это сообщение отредактировал(а) superVad - 10.1.2011, 10:37
PM MAIL   Вверх
Akella
Дата 10.1.2011, 11:57 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Творец
****


Профиль
Группа: Модератор
Сообщений: 18485
Регистрация: 14.5.2003
Где: Корусант

Репутация: 36
Всего: 329



Delphist, почитай про операторы as, is, про RTTI.
PM MAIL   Вверх
БелАмор
Дата 10.1.2011, 12:56 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 209
Регистрация: 10.6.2010
Где: Россия

Репутация: 5
Всего: 17



Поскольку тут пошла речь про as и is, думаю, нелишним будет обратить внимание на несколько неочевидных моментов:

1. is проверяет на приналдежность классу или его наследнику.
2. is предназначен только для поверки принадлежности классу, являющимся потомком по отношению к классу, к которому относится переменная, ссыляющаяся на проверяемый объект. В случаях, когда принадлежность к классу вытекает из типа переменной, компилятор вообще исключает проверку, подставляя True.
3. as предназначен для приведения типа с проверкой только к потомку, но никак не к предку. При попытке приведения типа к предку через as, as игнорируется. В этом случае следует использовать обычное приведение типа.

Ссылка: ПРОГРАММИСТ.Нецелевое использование оператора is
PM   Вверх
skyboy
Дата 10.1.2011, 12:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


неОпытный
****


Профиль
Группа: Модератор
Сообщений: 9820
Регистрация: 18.5.2006
Где: Днепропетровск

Репутация: 4
Всего: 260



Цитата(mes @  10.1.2011,  00:47 Найти цитируемый пост)
см. as  

и как это должно помочь?
Код

var obj: TControl;
...
obj = TButton.Create(Form1);
obj as TPanel // разве это проверка, является ли obj экземпляром класса TPanel?

PM MAIL   Вверх
Delphist
  Дата 10.1.2011, 13:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Delphist Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2145
Регистрация: 3.2.2004
Где: всегда в сети

Репутация: 2
Всего: 3



Цитата(skyboy @  10.1.2011,  13:58 Найти цитируемый пост)
и как это должно помочь?

Согласен

Добавлено @ 13:49
Цитата(БелАмор @  10.1.2011,  11:13 Найти цитируемый пост)
s проверяет принадлежность объекта классу или его наследнику, в большинстве случаев этого достаточно. 

оператор is делает неправильно оценку для моего случая, т.к. в моем TRawClass  Ower is TCustomClass, поэтому вызов
Код

var
   SecondClass: TSecondClass;
begin
   //вызов этого
   SecondClass := TSecondClass.Create;
  //приведет к тому, что в будет создан RawsClass и Owner := SecondClass;
   

   //затем вызов вот этого
   Second.Method;
end;   
    
  //приведет к вот этому
procedure TRawClass.Method;
begin
   
  if Owner is TSecondClass  then  [color=crimson]//и здесь результатом будет False, хотя Owner := SecondClass, a SecondClass: TSecondClass[/color]
end;


а нужно, чтобы если Owner := SecondClass или Owner := ThirdClass, то вызов if Owner is TSecondClass then (или if Owner is Наследники TSecondClass then) возвращал True
как это сделать?



Это сообщение отредактировал(а) Delphist - 10.1.2011, 13:59


--------------------
ProcessInfo 1-ая моя программа (аналог spyxx.exe с гораздо большим функц-ом - внедрение dll в адр. простр. процесса, перехват API-функций, разбор приложения на окна мн.др).
Когда-то давным-давно использовал это...
PM MAIL ICQ   Вверх
Delphist
Дата 10.1.2011, 13:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Delphist Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2145
Регистрация: 3.2.2004
Где: всегда в сети

Репутация: 2
Всего: 3



Цитата(Akella @  10.1.2011,  12:57 Найти цитируемый пост)
Delphist, почитай про операторы as, is, про RTTI. 

я и так про них все отлично знаю, еще раз внимательно посмотрите на мой пример


--------------------
ProcessInfo 1-ая моя программа (аналог spyxx.exe с гораздо большим функц-ом - внедрение dll в адр. простр. процесса, перехват API-функций, разбор приложения на окна мн.др).
Когда-то давным-давно использовал это...
PM MAIL ICQ   Вверх
БелАмор
Дата 10.1.2011, 14:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 209
Регистрация: 10.6.2010
Где: Россия

Репутация: 5
Всего: 17



Не может ли быть такой ситуации, что на момент вызова TRawClass.Method Owner по какой-либо причине равен nil, например, его вызов происходит в конструкторе до присвоения Owner, или по каким-либо другим причинам?
Указывает ли Owner на реально существующий объект в момент проверки?
PM   Вверх
Akella
Дата 10.1.2011, 15:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Творец
****


Профиль
Группа: Модератор
Сообщений: 18485
Регистрация: 14.5.2003
Где: Корусант

Репутация: 36
Всего: 329



Цитата(Delphist @  10.1.2011,  01:15 Найти цитируемый пост)
Как я должен написать в методе TRawClass.Method, чтобы узнать, что Owner является ли класс TSecondClass или классом унаследованных от TSecondClass (т.е. TThirdClass)

я, лично, не понял вопроса %)
PM MAIL   Вверх
Delphist
Дата 10.1.2011, 15:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Delphist Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2145
Регистрация: 3.2.2004
Где: всегда в сети

Репутация: 2
Всего: 3



Цитата(БелАмор @  10.1.2011,  15:38 Найти цитируемый пост)

Указывает ли Owner на реально существующий объект в момент проверки?

Да указывает, и это не важно сейчас. Вопрос мой совершенно в другом направлении,
я про то, что если написать
Код


procedure TRawClass.Method;
begin
   
  if Owner is TSecondClass  then 
    ShowMessage('Ура заработало');
end;

и вызвать 
Код

  SecondClass.RawClass.Method; 


то вместо ожидаемого сообщения, будет тишина, хотя когда создавался RawClass в constructor'e TSecondClass, то RawClass.Owner := Self = SecondClass'y
Как заставить  if Owner is TSecondClass  then  правильно отрабатывать

Добавлено @ 15:55
Цитата(Akella @  10.1.2011,  16:41 Найти цитируемый пост)
я, лично, не понял вопроса %) 

на примере показал

Это сообщение отредактировал(а) Delphist - 10.1.2011, 15:59


--------------------
ProcessInfo 1-ая моя программа (аналог spyxx.exe с гораздо большим функц-ом - внедрение dll в адр. простр. процесса, перехват API-функций, разбор приложения на окна мн.др).
Когда-то давным-давно использовал это...
PM MAIL ICQ   Вверх
БелАмор
Дата 10.1.2011, 16:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 209
Регистрация: 10.6.2010
Где: Россия

Репутация: 5
Всего: 17



Цитата(Delphist @  10.1.2011,  15:50 Найти цитируемый пост)
то вместо ожидаемого сообщения, будет тишина

А если написать:
Код

procedure TRawClass.Method;
begin
  ShowMessage(Owner.ClassName);
 
  if Owner is TSecondClass  then 
    ShowMessage('Ура заработало');
end;

... то какое имя класса будет показано перед тишиной?

Это сообщение отредактировал(а) БелАмор - 10.1.2011, 16:49
PM   Вверх
Delphist
Дата 10.1.2011, 18:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Delphist Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2145
Регистрация: 3.2.2004
Где: всегда в сети

Репутация: 2
Всего: 3



Цитата(БелАмор @  10.1.2011,  17:28 Найти цитируемый пост)
... то какое имя класса будет показано перед тишиной?

TSecondClass

Добавлено через 6 минут и 16 секунд
Проблема видать возникает что Owner изначально в TRawClass объявлен как TCustomClass,
и поэтому даже присвоение Owner := SecondClass, где SecondClass: TSecondClass не помогает
is вернет TCustomClass.
А вот как это исправить не знаю, единственный вариант, который пока вижу использовать
заместо Owner is TSecondClass использовать виртуальную функцию возвращающий Boolean
и переопределять ее у наследников.
Правда так не хочется делать


--------------------
ProcessInfo 1-ая моя программа (аналог spyxx.exe с гораздо большим функц-ом - внедрение dll в адр. простр. процесса, перехват API-функций, разбор приложения на окна мн.др).
Когда-то давным-давно использовал это...
PM MAIL ICQ   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Общие вопросы"
SnowyMetalFan
bemsPoseidon
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0703 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.