Delphi 如何制作这个OO?

Delphi 如何制作这个OO?,delphi,oop,delphi-2009,Delphi,Oop,Delphi 2009,很抱歉这个糟糕的标题,我是OOP新手,所以我不知道我需要做什么 比如说,我有10个不同的对象继承一个对象。它们有不同数量和类型的类成员,但它们都有一个共同的属性-可见 type TSObject=class(TObject); protected Visible:boolean; end; type TObj1=class(TSObject) private a:integer; ...(More members) end; TObj2=class

很抱歉这个糟糕的标题,我是OOP新手,所以我不知道我需要做什么

比如说,我有10个不同的对象继承一个对象。它们有不同数量和类型的类成员,但它们都有一个共同的属性-可见

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)
对于它们中的每一个,我都有一个变量

var Obj1:TObj1;
    Obj2:TObj2;
    Obj3:TObj3;
    ....(Other 7 objects)
规则1:一次只能初始化一个对象(其他对象必须被释放),使其可见

对于这个规则,我有一个全局变量

var CurrentVisibleObj:TSObject; //Because they all inherit TSObject
最后是一个改变可见性的过程

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;
ChangeObjVisibility(Obj3);
这是我的问题,我不知道如何初始化它,因为派生类是未知的(TObj1、TObj2、Tobj3…哪一个?)

我该怎么做

我简化了解释,在这个项目中,每个TFrame都有不同的控件,我必须以相同的方式设置可见/不可见(只保留一个初始化的帧)


再次为标题感到抱歉,我是OOP新手。

由于is-a关系,您甚至可以访问派生对象的基本属性。在您的例子中,您希望在多个对象之间拥有一个共享状态,考虑这一点的一种方法是创建一个管理器类来保存这些对象。它将只选择一个对象作为可见对象。您可能不需要包含对象上的visible属性,但此设计也允许这样做

容器

列出我的对象;
对象MyVisibleObject

您不应该每次更改帧的可见性时都创建和释放帧-它们应该始终处于初始化状态。

如果这是关于一组TFrame控件,并且您希望一次只显示其中一个控件,那么您不需要一直释放和创建它们。您可以将每个帧放在TPageControl的一页上,然后隐藏选项卡条并使用TPageControl的ActivePage属性更改可见帧

这是我的问题,我不知道怎么办 初始化它,因为 班级是 未知(TObj1、TObj2、Tobj3…哪个 一个?)

嗯,基本上有两种选择:

  • 要么将要创建的对象类型作为参数传递给方法,例如,调用方必须告诉您要创建什么

  • 您可以根据其他信息确定要创建的类型;一种简单的方法是创建一个与您最初传入的对象类型相同的对象(不知道这在您的上下文中是否有意义)


我已经有一段时间没有做任何严肃的Delphi工作了,但我想我模糊地记得在Delphi中有一种表达您想要的“类型”的方法。或者,您甚至可以基于作为字符串的类型名称创建给定类型的实例(例如,基于传入的字符串“TObj2”创建
TObj2
的实例)

这里的第一个问题是,您似乎假设可以将未初始化的变量传递给ChangeObjVisibility

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;
ChangeObjVisibility(Obj3);
在这里,如果Obj3是nil(或者更糟,是一个悬空指针),ChangeObjVisibility就无法知道它需要创建的对象的类型

获取要创建的frame类的一种方法是使用const数组或带有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;
如果框架不需要任何类型的特殊初始化,这将起作用

接下来,你可以打这样的电话:

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; 
过程ChangeCurrentFrame(NewFrameIndex:Integer);
var FrameClass:TSObjectclass;
vFrame:TSObject;
开始
FrameClass:=GetFrameClass(NewFrameIndex);
如果CurrentVisibleObj.ClassType FrameClass,则
开始
vFrame:=FrameClass.Create(nil);
SetCurrentFrame(vFrame);
结束;
结束;
程序SetCurrentFrame(newObj:TSObject);
开始
如果已分配(CurrentVisibleObj),则
CurrentVisibleObj.Free//释放旧对象
CurrentVisibleObj:=newObj//指定新对象
如果已分配(CurrentVisibleObj),则
CurrentVisibleObj.Visible:=真//设置新对象的可见性
结束;

在这里,SetCurrentFrame替换您ChangeObjVisibility(您在这里真正做的是更改当前帧,更改可见性只是一个“副作用”)

但它们值30mb内存。它们超过10个。我认为最好每次切换时都创建它们。@John-我明白您的意思。我们有一个VB承包商,他创建了一个包含几十个框架的大型客户档案表单,他只是翻转框架来显示不同类型的信息。这就拖累了整个系统,因为它使用了太多的资源。但那是1997年,奔腾II处理器,256MB内存(可能更少?我不记得了),还有。。。视窗3.1。在我看来,在创建/销毁UI元素时,过于吝啬UI可能会导致过度延迟。只是说…@约翰:这是另一个不分配和每次释放它们的观点!您不希望每次用户切换帧时都分配大量内存—这将花费很长时间。事实上,FastMM的内存分配和释放非常非常快。慢的部分是设置30 MB的组件@梅森,真的!我用两个帧(if,else if)测试了这一点。它在FastMM中运行得非常顺利,但我不知道如何使用所有帧。我使用了另一种方法通过类类型。我认为更好,但你写的东西花了你的时间,为此,我很感激。+1&Accept。将类传递给ChangeObjVisibility会对每个类的初始化造成一些限制。由于这个原因,我更喜欢传递一个已经初始化的对象,而不是传递类类型。它使设计更加灵活。+1启动应用程序可能需要几毫秒的额外时间,但在那之后,事情会变得快速而顺利。另一个优点是,在来回翻转时,帧的状态保持不变。这样,在IDE中维护GUI就容易多了。