Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 07.04.2011, 13:39   #1
phomm
personality
Старожил
 
Аватар для phomm
 
Регистрация: 28.04.2009
Сообщений: 2,882
По умолчанию Определение типа класса по переменной на объект этого класса при компиляции

Задача такая у меня, возможно, покажется извращенской.

Имеем такое:

Код:
procedure dosmth(sender : tobject);
var
  cls : tsomeclass; // это именно тот тип, которым будет sender
begin
cls := sender as tsomeclass;
cls.dosmth;
end;
Я хочу, чтобы вместо красного было что-то такое, что позволит АВТОМАТОМ (имею ввиду без слова tsomeclass) В COMPILE-TIME определять тип класса по самой переменной.

Пробовал вот что :
cls.classtype - не подходит
гуглил возможность перевода имени класса в идентификатор класса (если я корявый, ткните в меня google/lmgtfy ссылкой)
есть возможно хитрости с класстайп и классинфо, но они вроде только на рантайм, а мне надо компайл-тайм

Мне кажется, что есть какое-то изящное решение. Например, когда мы в дельфи наводим мышкой на переменную объектного типа, то видим её тип, возможно , этому есть инструмент дельфи какой-то, хотя скорее всего, это делает среда.

Грубыми словами, мне надо вместо самого идентификатора класса получать его(идентификатор класса) из переменной экземпляра класса.

Спасибо вам, гуру !

Вполне допускаю, что будут ответы : так все и делают ! но, может, быть всё-таки, можно задать только 1 раз имя класса, в var ?

Последний раз редактировалось phomm; 07.04.2011 в 13:49.
phomm вне форума Ответить с цитированием
Старый 07.04.2011, 14:07   #2
Человек_Борща
Старожил
 
Аватар для Человек_Борща
 
Регистрация: 30.12.2009
Сообщений: 11,426
По умолчанию

Если я правильно понял. то структура TVarRec;(System.pas) поможет. Там же TVarType и TVarData

Ещё есть TValueType

Последний раз редактировалось Человек_Борща; 07.04.2011 в 14:15.
Человек_Борща вне форума Ответить с цитированием
Старый 07.04.2011, 14:07   #3
Аватар
Старожил
 
Аватар для Аватар
 
Регистрация: 17.11.2010
Сообщений: 18,922
По умолчанию

Есть вариант cls := tsomeclass(sender); а больше ни как
Если бы архитекторы строили здания так, как программисты пишут программы, то первый залетевший дятел разрушил бы цивилизацию
Аватар вне форума Ответить с цитированием
Старый 07.04.2011, 14:20   #4
GunSmoker
Старожил
 
Регистрация: 13.08.2009
Сообщений: 2,581
По умолчанию

Integer(cls) := Integer(sender);

Но это ппц как небезопасно. Я бы шесть раз подумал, прежде чем такое делать, и... так и не сделал бы.

P.S. Классы и объекты не путай.
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
GunSmoker вне форума Ответить с цитированием
Старый 07.04.2011, 16:06   #5
veniside
Старожил
 
Регистрация: 03.01.2011
Сообщений: 2,508
По умолчанию

Если я правильно понял задачу (в чём я сомневаюсь), есть некая иерархия классов:

Код:
type
  TAnimal = class
  public
    procedure voice(); virtual;
  end;

  TDog = class(TAnimal)
  public
    procedure voice(); override;
  end;

  TCat = class(TAnimal)
  public
    procedure voice(); override;
  end;
Теперь мы хотим сделать процедуру, которая будет принимать класс для создания животного. Для этого вводим новый тип, и пишем процедуру:

Код:
type
  myAnimals = class of TAnimal;

procedure doVoice(animalClass: myAnimals);
var
  instance: TAnimal;
begin
  instance := animalClass.Create();
  instance.voice();
  instance.Free();
end;
Вызывать такую процедуру можно передав ей имя нужного нам класса:

Код:
procedure TForm1.FormCreate(Sender: TObject);
begin
  doVoice(TCat);
end;
"Когда приходит положенное время, человек перестаёт играть в пинбол. Только и всего."
veniside вне форума Ответить с цитированием
Старый 07.04.2011, 17:42   #6
phomm
personality
Старожил
 
Аватар для phomm
 
Регистрация: 28.04.2009
Сообщений: 2,882
По умолчанию

Всем спасибо , что откликнулись, всем плюсы )

Человек_Борща, почитал справку, по-моему к моему случаю сие не относится
Аватар, этот случай даже не рассматриваю ) он всё равно ведь с использованием Tsomeclass , да и приведение типов для классов лучше делать с as, ибо генерит исключение при несоответствии, в отличие от прямого приведения(как Вы указали)
GunSmoker, спасибо, очень дельный совет, я предполагал , что есть подобное решение из разряда хаков, скорее всего, конечно, не буду использовать, опасность такого метода, полагаю, заключается в отсутствии приведения типов ? ведь sender может быть и потомком оригинального класса
veniside, я так понял, Вы расписали шаблон/паттерн Builder , вполне возможно, если вывести функцию, которая будет "строить" объекты, то можно достигнуть означеной цели, но мне кажется указания конкретного класса избежать не удастся, хоть и будет опосредовано (в функции), ведь класс надо передавать в функцию (в Вашем примере Tcat), да и решение, всё же достаточно объемным будет (я рассчитывал на пару строчек)

Хотелось бы несколько прояснить , возможно, так будет яснее, имеем такое дело :
Код:
var cls : tsomeclass1;
...
proc do1(sender : tobject);
begin
cls := autotypecast(sender);
cls.do1;
end;
...
proc doN(sender : tobject);
begin
cls := autotypecast(sender);
cls.doN;
end;
Как запрограммировать такой autotypecast, который бы позволил оперативно перенастраивать работу модуля, при необходимости смены типа объектов-caller'ов только лишь меняя объявление cls , например, cls : tsomeclass1 cls : tsomeclass2 ?

Извините, я понимаю что приведенный пример сферичен в вакууме, и проще написать cls := sender as Tsomeclass1, а при необходимости перенастроить, объявить cls : tsomeclass и нажимая F9 просто переписать те несколько строчек на другой класс, но надежда на некий красивый выход есть, ведь я уже приводил пример со средой дельфи, может что-то такое....

Последний раз редактировалось phomm; 07.04.2011 в 18:31.
phomm вне форума Ответить с цитированием
Старый 07.04.2011, 18:05   #7
Человек_Борща
Старожил
 
Аватар для Человек_Борща
 
Регистрация: 30.12.2009
Сообщений: 11,426
По умолчанию

Есть ещё TClassList
Человек_Борща вне форума Ответить с цитированием
Старый 07.04.2011, 18:33   #8
veniside
Старожил
 
Регистрация: 03.01.2011
Сообщений: 2,508
По умолчанию

> возможно, так будет яснее

честно говоря, понятней не стало. Проблема даже не в классе, а вот в этом:

Код:
cls.do1;
cls.doN;
если do1() и doN() объявлены как виртуальные в базовом для tsomeclass1 и для tsomeclass2 классе, то и делать больше ничего не надо, дельфи сама знает, как полиморфизм должен сработать.

Ну вот сменили вы класс у cls с tsomeclass1 на tsomeclass2. Оба эти класса должны иметь методы do1() и doN(), так? Тогда почему бы не сделать для них базовый класс tsomeclassbase, эти методы объявить виртуальными и насладиться работой ООП в действии?
"Когда приходит положенное время, человек перестаёт играть в пинбол. Только и всего."
veniside вне форума Ответить с цитированием
Старый 07.04.2011, 19:01   #9
phomm
personality
Старожил
 
Аватар для phomm
 
Регистрация: 28.04.2009
Сообщений: 2,882
По умолчанию

кажется , получилось... сам не верю , что не аксесвиолейшенит, копирую прямо из проекта, чтобы не на абстрактном примере.
Код:
type
  tgridclass = class of tcustomdrawgrid;
var
  caller : TCustomDrawGrid;
...
procedure TForm5.GridMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
begin
  tgridclass(caller) := tgridclass(sender);
  caller.colcount := 6;
  ... and so on
end;
ну и другие процедуры. Теперь переброска, например , с Tdrawgrid на Tstringgrid производится всего в 2 строчки, меняю тип класса и переменную, и по коду бегать не надо.
Получается, что теперь идентификатор для тайпкаста можно вынести в секцию объявления, и не заботиться о перекройке проекта, всё будет автоматом

Хочется ещё узнать, легально ли такое ? не будет ли проблемок ?
phomm вне форума Ответить с цитированием
Старый 07.04.2011, 19:40   #10
eduard93
Форумчанин
 
Регистрация: 06.12.2010
Сообщений: 300
По умолчанию

Нечто странное у вас. В любом случае работа с одним классом как с другим возможна только если они совместимы. К примеру TForm1 и TForm совместимы:
Код:
procedure TForm1.FormCreate(Sender: TObject);
var
  f: TForm;
begin
  f := Sender as TForm;
  f.AlphaBlend := True;
  f.AlphaBlendValue := 200;
end;
eduard93 вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Ошибка при присвоении объекту производного класса объекта базового класса с исп. явного приведения типов Lanx Помощь студентам 0 06.04.2011 20:24
Шаблоны - нужно создать объект класса abc в котором вместо aa использовался бы объект класса fff? Farrel Общие вопросы C/C++ 2 13.11.2010 17:37
Создание класса с полем типа TStringList. Ошибка при его заполнении Son Общие вопросы Delphi 8 13.04.2010 21:38
Параметр конструктора класса = объект этого класса nazavrik Общие вопросы C/C++ 6 14.02.2010 13:48
Если в классе объявить объект другого класса,будет ли видно переменные первого класса из объекта второго? TwiX Общие вопросы Delphi 3 15.11.2009 00:54