Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Общие вопросы > ООП


Автор: omickron 20.7.2011, 18:01
Имеем: 

Код

type 
  TMyClass = class(TObject);
  TMyClass1=class(TMyClass);
  TMyClass2=class(TMyClass);

var
  my,new:TMyClass;
  
begin
  my := TMyClass1.Create;
  //todo: Задача: в переменной new создать объект того же класса, что и объект my.
  // new := my.ClassType.Create; // не работает, не пускает компилятор, т.к. ClassType = class of TObject
end;


Вопрос: как в переменную засунуть объект такого же класса, что и имеющийся объект?

Автор: AKATAN 20.7.2011, 21:41
Код

new := TMyClass.Create;

или обращаться к TMyClass нельзя?

Автор: pseud 21.7.2011, 09:14
Код

  if my is TMyClass1 then
    new := TMyClass1.Create
  else if my is TMyClass2 then
    new := TMyClass2.Create;

Автор: skyboy 21.7.2011, 14:28
лучше - воспользоваться паттерном "http://ru.wikipedia.org/wiki/%D0%9F%D1%80%D0%BE%D1%82%D0%BE%D1%82%D0%B8%D0%BF_%28%D1%88%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD_%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F%29". тогда будет типа такого:
Код

source = TMyClass1.create();
target = source.clone();

можно - воспользоваться RTTI и написать что-то навроде:
Код

source = TMyClass1.create();
target = getClass(source.className).create();

но, кажется, только для определенных классов будет работать(в плане иерархии у "подходящих" классов должен быть предком TPersistentClass, кажется)

Автор: omickron 21.7.2011, 17:51
AKATAN, блин smile просто замечательный ответ smile

pseud, а теперь представьте, что у вас пара десятков наследников TMyClass. Представили? Как будет выглядеть Ваш код?

skyboy, а прототипы разве реализуются в Delphi? Интересует 2007 версия.
Насчёт GetClass - если не ошибаюсь, она вернёт то же значение, что и source.ClassType. А это не срабатывает, как я писал в первом посте.

Автор: bems 22.7.2011, 06:49
Код

type
  TMyClass = class(TObject);
  TMyMetaclass = class of TMyClass;

  TMyClass1=class(TMyClass);
  TMyClass2=class(TMyClass);
var
  my,new:TMyClass;

begin
  my := TMyClass1.Create;
  new := TMyMetaclass(my.ClassType).Create;
end.

конструктор лучше бы сделать виртуальным

Автор: omickron 23.7.2011, 12:17
Спасибо! TMyMetaclass(my.ClassType).Create - то, что надо!

Насчёт виртуального конструктора - вроде он должен обязательно быть для динамического определения типа создаваемого объекта.
Но почему-то в приведённом Вами коде ShowMessage(new.ClassName); показывает "MyClass1". MyClass - просто наследник Tobject, а у него конструктор не виртуальный, обычный.

Блин, почему? smile

Автор: bems 23.7.2011, 13:17
потому что my.ClassType равен TMyClass1. Приведение к TMyMetaclass нужно только чтобы выражение удовлетворяло правилам совместимости типов.
А вот тело конструктора выполняется от TMyClass. Сделай такой эксперимент, и увидишь:
Код

program Project14;

{$APPTYPE CONSOLE}

type
  TMyClass = class(TObject)
    constructor Create;
  end;
  TMyMetaclass = class of TMyClass;

  TMyClass1=class(TMyClass)
    constructor Create;
  end;

var
  my,new:TMyClass;

{ TMyClass1 }

constructor TMyClass1.Create;
begin
  inherited;
  writeln('Object: ', Cardinal(Self), ' ClassName: ', ClassName, ' Constructor: TMyClass1.Create');
end;

{ TMyClass }

constructor TMyClass.Create;
begin
  writeln('Object: ', Cardinal(Self), ' ClassName: ', ClassName, ' Constructor: TMyClass.Create');
end;

begin
  my := TMyClass1.Create;
  writeln;
  new := TMyMetaclass(my.ClassType).Create;
  readln
end.


Такой объект я назвал бы калекой. Если сделать конструктор виртуальным - проблема исчезает

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)