Форум: "Основная";
Текущий архив: 2003.11.13;
Скачать: [xml.tar.bz2];
ВнизНебольшой вопрос про наследование Найти похожие ветки
← →
SkyRanger (2003-10-31 16:21) [0]У меня есть класс TOpenGL
TOpenGL = class
WinContent : hDC; //Контекст окна
GLContent : hGLRC; //Контекст OpenGL
GLFOV : GLFloat; //Значение FOV
MaxX, MaxY : Integer; //Максимальные значения X и Y (Разрешение экрана)
WinHeight : Integer; //Высота окна
WinWidth : Integer; //Ширина окна
///
public
procedure InitOpenGL(WinhDC : hDC; cBits,dBits : byte; fov : GLFloat; glWinHeidht, glWinLength : Integer);//Инициализирует OpenGl
procedure DestroyOpenGL;//Инициализирует OpenGl
procedure ResizeWindow(WinMaxWidth, WinMaxHeigh : Integer);//Сохраняет пропорции при изменении размера окна
procedure UpdateWindow; //Обновляет окно
private
procedure SetDCPixelFormat(mhdc : hDC;cBits,dBits : byte);//Устанавливает формат пикселей для устройства
end;
так же есть наследуемый от него класс TGLConsole
TGLConsole = class (TOpenGL)
MessageList:array [0..100] of String;
fnt:TGLFont;
ConsoleList:GLUInt;
ConsoleTex:TGLTExture;
Constructor Init(Msg:String);
Procedure DrawConsole;
Destructor Destroy;
end;
Наследование я сделал чтобы каждый раз не передавать через параметры контексты окна, размеры окна и контексты OpenGL это все гомерно получается и некраиво.
Теперь, по идее хотелось бы нписать что то типа
Console:=MyOpenGl.OpenGL;
Но косяк в том что по правилам енто невозможно так как присваивание возможно тока в направлении Родитель<-наследник
Подскажите плмз наиболее оптимальный метод решения. Т.е. Автоматического заполнения наследуемых полей у потомка из полей родителя...
← →
Stratos (2003-11-01 03:25) [1]попробуй так:
допустим
var
Console: TGLConsole;
OpenGL: TOpenGL;
...
begin
(Console as TOpenGL):= OpenGL;
end;
← →
SkyRanger (2003-11-01 07:14) [2]>Stratos © (01.11.03 03:25) [1]
Не катит! Выдает мол типы не совместимы и левая часть не может быть назначенна...
Почитал хелп, там написанно что так должно работать вот пример из хелпа:
type
TAncestor = class
Value: Integer;
end;
TDescendant = class(TAncestor)
Value: string; // hides the inherited Value field
end;
var
MyObject: TAncestor;
begin
MyObject := TDescendant.Create;
MyObject.Value := "Hello!"; // error
TDescendant(MyObject).Value := "Hello!"; // works!
end;
Я так подумал если написать так TOpenGL(Console).:=OpenGL;
то должно сработать... Ан нет... пришлось обломиться...
Есть еще предложения???
Вписывать в объявление класса экземпляр класса TOpenGl не хочется, так как приджется следить за выделением и освобождением памяти... А раз он наследуется в дочернем классе то почему бы не заполнить все поля автоматически, а не вводить в Init конструктор кучу присваиваний...
← →
yo (2003-11-01 09:15) [3]Коирование в таком виде, в котором ты хочешь - это всего
лишь копирование указателей.
А тебе, насколько я понял, нужно именно скопировать данные из одного объекта в другой, что-то вроде
Console.Assign(OpenGL);
← →
SkyRanger (2003-11-01 11:23) [4]Нефига! У меня класс не потомок TPersistent и не нада ентого!
Пытался встроить в свой класс методы из TPersistent нефига не вышло и тем более не понятно где тут он производит непосредственно присваивание. Создается ощющение что этот код кроме обработки ошибок больше нефига не делает!!!
procedure TPersistent.Assign(Source: TPersistent);
begin
if Source <> nil then Source.AssignTo(Self) else AssignError(nil);
end;
procedure TPersistent.AssignError(Source: TPersistent);
var
SourceName: string;
begin
if Source <> nil then
SourceName := Source.ClassName else
SourceName := "nil";
raise EConvertError.CreateResFmt(@SAssignError, [SourceName, ClassName]);
end;
procedure TPersistent.AssignTo(Dest: TPersistent);
begin
Dest.AssignError(Self);
end;
← →
SkyRanger (2003-11-01 11:27) [5]Или же тут придется самомоу писать свой Assign??? Как у TFont???
procedure TFont.Assign(Source: TPersistent);
begin
if Source is TFont then
begin
Lock;
try
TFont(Source).Lock;
try
FontManager.AssignResource(Self, TFont(Source).FResource);
Color := TFont(Source).Color;
if PixelsPerInch <> TFont(Source).PixelsPerInch then
Size := TFont(Source).Size;
finally
TFont(Source).Unlock;
end;
finally
Unlock;
end;
Exit;
end;
inherited Assign(Source);
end;
← →
Юрий Зотов (2003-11-01 12:42) [6]Так Вы что конкретно хотите сделать - присвоить ссылку или скопировать содержимое? Если первое, то никакой Assign Вам не нужен.
Вообще, вопрос непонятен. Давайте уберем все лишнее и сведем задачу к сути. Есть два класса:
TParent = class // прямой наследник TObject
...
end;
TChild = class(TParent)
...
end;
Теперь скажите - что конкретно требуется сделать?
← →
SkyRanger (2003-11-01 13:09) [7]Нужно чтобы все поля принадлежащие классу TParent наследованные в классе TChild обновились автоматически... Т.е. я создаю класс
TParent затем класс TChild. При инициализации класса TParent его поля заполняются некоторой информацией, которую нужно без лишней мороки перенести в класс TChild т.к. она в нем неоднократно используется, и передавать каждому методу эти данные как параметр неэффективно!
← →
Palladin (2003-11-01 13:24) [8]Создай record с нужными полями и работай с его экземплярами.
Это избавит тебя от кучи :=
← →
Юрий Зотов (2003-11-01 13:38) [9]Надо просто создать экземпляр класса TChild и ничего никуда "переносить" не нужно. Он же наследник - а потому вся инициализация будет унаследована Нужно только грамотно написать классы, вот и все. Например:
type
TParent = class
protected
procedure Initialize; virtual;
public
constructor Create;
end;
TChild = class(TParent)
protected
procedure Initialize; override;
end;
constructor TParent.Create;
begin
inherited;
Initialize
end;
procedure TParent.Initialize;
begin
... // Все, что нужно инициализировать ТОЛЬКО в классе TParent
end;
procedure TChild.Initialize;
begin
inherited; // Инициализирутся унаследованные поля.
... // Собственная дополнительная инициализация
end;
Если в классе TChild собственная дополнительная инициализация не требуется, то и метод Initialize в нем не нужен - из конструктора вызовется унаследованный Initialize.
← →
SkyRanger (2003-11-01 13:54) [10]А если этот клас инициализирует OpenGL и ДОЛЖЕ быть создан и вызван ТОЛЬКО 1 раз, но данные которые он получает в процессе работы необходимы в последующем???
Тут я имею ввиду не описания классов, а ЭКЗЕМПЛЯРЫ т.е. прошедшие
Parent:=TParent.Create;
Parent.Init(wnd,16,16,45, WinHeight,WinWidth);
Child:=TChild.Create;
Причем Parent:=TParent.Create;
Обязательно должен быть вызван первым и данные которые он получит в процессе своей работы, а также переданные ему wnd,16,16,45, WinHeight,WinWidth должны быть доступны в наследнике Child.
Может я что то не так понимаю, но мне нужно чтобы работало все так. Можно это сделать как нибудь???
То что вы предлагаете ведет к наследованию методов, т.е. кода, который должен выполняться ВСЕГО ОДИН РАЗ. причем наследников у этого класса будет очень много!
Такая вот непростая ситуация...
← →
Юрий Зотов (2003-11-01 15:27) [11]interface
type
TParent = class
protected
procedure Initialize; virtual;
public
constructor Create;
destructor Destroy; overide;
end;
TChild = class(TParent)
protected
procedure Initialize; override;
procedure AssignCurrentProps;
end;
function GetPrimary: TParent;
implementation
var
Primary: TParent;
function GetPrimary: TParent;
begin
if Primary = nil then TParent.Create;
Result := Primary
end;
constructor TParent.Create;
begin
if Primary = nil then
Primary := Self
else
if ClassType = TParent then
raise Exception.Create("Primary object already exists");
inherited;
Initialize
end;
destructor TParent.Destroy;
begin
if Primary = Self then Primary := nil;
inherited
end;
procedure TParent.Initialize;
begin
if Primary = Self
begin
... // Инициализация OpenGL.
... // Другой код, который должен выполняться только 1 раз.
end;
... // Инициализация еще чего-то, если надо
end;
procedure TChild.Initialize;
begin
inherited; // Унаследованная инициализация, кроме OpenGL.
... // Собственная дополнительная инициализация, если надо
AssignCurrentProps
end;
procedure TChild.AssignCurrentProps;
// Назначает текущие значения свойств объекта Primary
begin
Prop1 := Primary.Prop1;
Prop2 := Primary.Prop2;
... // И так далее
end;
Теперь:
1. Первый вызов TParent.Create будет создавать и инициализировать объект класса TParent, а кроме того будет инициализировать OpenGL и переменную Primary. Доступ к этому объекту извне модуля осуществляется через функцию GetPrimary, причем при первом ее вызове все создается и инициализируется автоматически.
2. При попытке вызвать TParent.Create во второй раз получим сообщение об ошибке, а второй объект создан не будет. Не будет выполнена и повторная инициализация OpenGL. Значение переменной Primary тоже не изменится - она по-прежнему будет указывать на первый объект TParent.
3. При вызове TChild.Create будет создан и принициализирован объект класса TChild. При этом повторная инициализация OpenGL не выполняется, а все нужные свойства свежесозданного объекта автоматически получат те же значения, которые они в данный момент имеют у объекта Primary.
4. Объектов класса TChild или его потомков может быть создано сколько угодно.
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2003.11.13;
Скачать: [xml.tar.bz2];
Память: 0.49 MB
Время: 0.032 c