Reputation: 35522
Sorry for the poor title,I'm new to OOP so I don't know what is the term for what I need to do.
I have, say, 10 different Objects that inherit one Object.They have different amount and type of class members,but all of them have one property in common - Visible.
type TSObject=class(TObject);
protected
Visible:boolean;
end;
type
TObj1=class(TSObject)
private
a:integer;
...(More members)
end;
TObj2=class(TSObject)
private
b:String;
...(More members)
end;
...(Other 8 objects)
For each of them I have a variable.
var Obj1:TObj1;
Obj2:TObj2;
Obj3:TObj3;
....(Other 7 objects)
Rule 1: Only one object can be initialized at a time(others have to be freed) to be visible.
For this rule I have a global variable
var CurrentVisibleObj:TSObject; //Because they all inherit TSObject
Finally there is a procedure that changes visibility.
procedure ChangeObjVisibility(newObj:TSObject);
begin
CurrentVisibleObj.Free; //Free the old object
CurrentVisibleObj:=newObj; //assign the new object
CurrentVisibleObj:= ??? //Create new object
CurrentVisibleObj.Visible:=true; //Set visibility to new object
end;
There is my problem,I don't know how to initialize it,because the derived class is unknown(TObj1,TObj2,Tobj3...Which one?).
How do I do this?
I simplified the explanation,in the project there are TFrames each having different controls and I have to set visible/not visible the same way(By leaving only one frame initialized).
Sorry again for the title,I'm very new to OOP.
Upvotes: 1
Views: 420
Reputation: 6467
One of the first problem here is that you seem to assume you can pass an uninitialized variable to ChangeObjVisibility.
ChangeObjVisibility(Obj3);
Here, if Obj3 is nil(or worse, a dangling pointer), ChangeObjVisibility has no way to know what is the type of the object it needs to create.
One of the way you could get the class of frame to create is with an array of const, or a function with a case.
type
TSObjectClass = class of TSObject;
const
ObjectClasses = array[0..X] of TSObjectClass = (TObj1, TObj2, TObj3, ...)
function GetFrameclass(Index : Integer) : TSObjectClass;
begin
Result := ObjectClasses[Index]
OR
case Index of
0 : Result := TObj1;
1 : Result := TObj2;
(...)
end;
end;
That will work if the frame doesn't need any kind of special initialization.
Next, you could have a call like this one :
procedure ChangeCurrentFrame(NewFrameIndex : Integer);
var FrameClass : TSObjectclass;
vFrame : TSObject;
begin
FrameClass := GetFrameClass(NewFrameIndex);
if CurrentVisibleObj.ClassType <> FrameClass then
begin
vFrame := FrameClass.Create(nil);
SetCurrentFrame(vFrame);
end;
end;
procedure SetCurrentFrame(newObj:TSObject);
begin
if Assigned(CurrentVisibleObj) then
CurrentVisibleObj.Free; //Free the old object
CurrentVisibleObj:=newObj; //assign the new object
if Assigned(CurrentVisibleObj) then
CurrentVisibleObj.Visible:=true; //Set visibility to new object
end;
Here, SetCurrentFrame replace you ChangeObjVisibility(What you really do here is change the current frame, changing the visibility is just a "side effect")
Upvotes: 1
Reputation: 754538
There is my problem,I don't know how to initialize it,because the derived class is unknown(TObj1,TObj2,Tobj3...Which one?).
Well, there are basically two options:
either you pass in the type of the object to be created as a parameter to your method, e.g. the caller has to tell you what it wants to be created
you can determine what type to create from some other information; one easy way would be to create an object of the same type as the one you originally passed in (don't know if that makes sense in your context)
It's been a while since I've done any serious Delphi work, but I think I vaguely remember there is a way in Delphi to express a "type" that you want to have. Or maybe you're even able to create an instance of a given type based on the name of the type as a string (e.g. create an instance of TObj2
based on the string "TObj2" being passed in)
Upvotes: 1
Reputation: 84550
If this is about a group of TFrame controls, and you want only one of them to be visible at a time, you don't need to go freeing and creating them all the time. You could just put each frame on one page of a TPageControl, then hide the tab strip and change the visible frame using the TPageControl's ActivePage property.
Upvotes: 1
Reputation: 7153
You shouldn't be creating and freeing your frames every time you want to change their visibility - they should all always be initialized all the time.
Upvotes: 0
Reputation: 6353
You can access a base property even on a derived object because of is-a relationship. In your case, you want to have a shared state among several objects, one way to think about this is to create a manager class which will hold the objects. It will only have one object selected as the visible object. You may not need the visible property on the contained objects but this design also permits that.
Container
List MyObjects; Object MyVisibleObject;
Upvotes: 0