Форум: "Начинающим";
Текущий архив: 2007.12.30;
Скачать: [xml.tar.bz2];
ВнизВопрос про ООП Найти похожие ветки
← →
ВаняЯ (2007-12-06 21:42) [0]У меня есть класс и его наследник. В коде программы в зависимости от условия нужно создавать или изначальный экземпляр класса или его наследник. Как в таком случае следует поступить? (Ну переменная должна быть одна, см. неработающий пример)
TMyClass1 = class(...)
private
Timer: TTimer;
....
FStr1: string;
public
constructor Create; virtual;
procedure Go1; virtual;
property str1: string read FStr1 write FStr1;
end;
TMyClass2 = class(TMyClass1)
private
FStr2: string;
....
public
constructor Create; override;
procedure Go1; override;
property str2: string read FStr2 write FStr2;
end;
------
var
Class: TMyClass1;
begin
Class := TMyCalss2.Create;
Class.str2 := "test"; // Error
← →
Юрий Зотов © (2007-12-06 21:50) [1]Нужно подсказать компилятору фактический класс переменной. Иначе он использует тот, с которым она объявлена, а в нем str2 нет.
var
AClass: TMyClass1;
begin
AClass := TMyClass2.Create;
TMyClass2(AClass).str2 := "test";
← →
ВаняЯ (2007-12-06 21:53) [2]А такая практика, как у меня в примере - нормальная, или это извращение?
← →
Юрий Зотов © (2007-12-06 21:56) [3]> ВаняЯ (06.12.07 21:53) [2]
Нормальная. В VCL подобное часто используется.
← →
Sergey Masloff (2007-12-06 21:56) [4]Юрий Зотов © (06.12.07 21:50) [1]
А тогда на фига весь сыр-бор? Если хочется полиморфизма то интерфес объекта должен быть одинаков в данном контексте. То есть уж либо
TMyClass1 = class(...)
private
Timer: TTimer;
....
FStr1: string;
public
constructor Create; virtual;
procedure Go1; virtual;
property str1: string read FStr1 write FStr1;
property str2: string read DoNothing write DoNothing;
end;
либо другие альтернативные механизмы.
Вопрос естественно не тебе а автору топика ;-)
← →
Юрий Зотов © (2007-12-06 22:01) [5]> Sergey Masloff (06.12.07 21:56) [4]
Аналог - TStrings и TStringList. Потомок расширяет интерфейс предка.
Обычное дело - объявляем переменную класса предка, а создаем экземпляр потомка. Если юзаем НЕрасширенный интерфейс, то делаем это напрямую (а полиморфизм сохраняется), если расширенный - приводим класс.
← →
Sergey Masloff (2007-12-06 22:17) [6]Юрий Зотов © (06.12.07 22:01) [5]
Дело-то обычное только использовать нужно с осторожностью а то ведь появится класс TMyClass3 у которого нет str2 а приведение к нему сработает
program Project2;
{$APPTYPE CONSOLE}
uses
SysUtils;
type
TMyClass = class(TObject)
constructor Create(); virtual;
end;
TMyClass2 = class(TMyClass)
fInt : Integer;
fInt2 : Integer;
constructor Create(); reintroduce; override;
end;
TMyClass3 = class(TMyClass)
fInt : Integer;
constructor Create(); reintroduce; override;
end;
var
c : TMyClass;
{ TMyClass }
constructor TMyClass.Create;
begin
end;
{ TMyClass2 }
constructor TMyClass2.Create;
begin
inherited;
fInt := 1;
fInt2 := 2;
end;
{ TMyClass3 }
constructor TMyClass3.Create;
begin
inherited;
fInt := 3;
end;
begin
c := TmyClass3.Create();
Writeln(TMyClass2(c).fint);
Writeln(TMyClass2(c).fint2);
Readln;
end.
Причем в этом примере ладно а в реальном приложении он почитает что-то за границами своего экземпляра.
Ты-то это знаешь, а вот знает ли это каждый?
Страницы: 1 вся ветка
Форум: "Начинающим";
Текущий архив: 2007.12.30;
Скачать: [xml.tar.bz2];
Память: 0.46 MB
Время: 0.006 c