我正在编写一个应用程序,该应用程序映射出一个目录结构,该目录结构需要尽可能多地保存有关每个文件的信息,以便最终用户可以应用自定义过滤器来操作其中的文件和文件夹。同时进行文件搜索的类将基本信息提供回UI,以使最终用户了解涉及多少数据。我想要完成的是通过属性递归到类的子对象以获取我需要的信息,这样我只需要访问顶级类就可以获得所需的信息,而不必担心信息在任何数量的子类中。
type
TSomeClass = class(TObject)
private
FContainerForSubObjects: TObjectList<TSomeClass>;
FSomethingToBeCounted: Integer;
FHasTheDataChanged: Boolean;
private
function GetSomethingToBeCounted: Integer;
function GetHasTheDataChanged: Boolean;
public
property SomethingToBeCounted: Integer read GetSomethingToBeCounted;
property HasTheDataChanged: Boolean read GetHasTheDataChanged;
使类声明更有意义。像这样看待它。 ContainerForSubObjects
包含一个文件夹,所以如果您要查看您的硬盘驱动器,根类将是C:\如果有一个名为data的文件夹,则会有一个表示C:\ Data文件夹的子对象和SomethingToBeCounted
将是每个文件夹中的文件数。
现在我想在GetSomethingToBeCounted
函数中做什么,如下所示
SomethingToBeCounted
属性,而该属性又应调用GetSomethingToBeCounted
函数以返回类 BUT <{1}}字段的值函数应该根据类的FSomethingToBeCounted
状态的条件行动这是我希望递归的地方
HasTheDataChanged
属性设置为false,则任何包含的子对象都是最新的,那么它应该返回它的值,不再需要进行处理HasTheDataChanged
属性设置为true,则数据不是最新的,应重新计算并返回新的重新计算值。它还应该设置适当的HasTheDataChanged
状态,以减少进一步的重新处理。 我还假设必须使用HasTheDataChanged属性来完成这种类似的传播,这样如果值在树的中间某处发生变化,所有父对象都会相应地更新。
希望这些要求有意义
现在问题的关键。首先。我的想法是正确的,只是通过访问子对象属性,正确的值将传播到根对象,所以当可能有数千个子对象时,我不必花费无数的代码行搜索每个子对象。或者这是我试图在这里重新发明轮子的情况,我只是在寻找一个已经存在的类并且可以使用而不是自己制作。最后但并非最不重要。这会是最有效的做事方式吗?
答案 0 :(得分:2)
我没有遇到过你想做的事情的现有组件,所以写你自己似乎是合理的。
你的方法会起作用,是我多次使用过的方法。您有一个递归数据结构,TSomeClass
包含更多TSomeClass
个对象的列表。以任何其他方式遍历这个结构会更复杂。
答案 1 :(得分:2)
对于这样的事情,我可能会朝另一个方向前进。我没有让父对象试图找出哪些子对象发生了变化,而是让一个子对象在发生更改时通知其父对象,然后通知其父对象及其父对象,依此类推。让信息向上冒泡,而不是向下搜索。这将大部分工作放在启动更改的活动上,并使搜索速度更快,因为所有信息都预先缓存在树中而无需寻找它。
type
TSomeClass = class(TObject)
private
FParent: TSomeClass;
FSubObjects: TObjectList<TSomeClass>;
FSomethingToBeCounted: Integer;
FHasTheDataChanged: Boolean;
procedure Changed;
protected
procedure SubObjectChanged(ASubObject: TSomeClass);
public
constructor Create(AParent: TSomeClass = nil);
destructor Destroy; override;
procedure DoSomethingToMakeAChange;
property SomethingToBeCounted: Integer read FSomethingToBeCounted;
property HasTheDataChanged: Boolean read FHasTheDataChanged;
end;
constructor TSomeObject.Create(AParent: TSomeClass = nil);
begin
inherited Create;
FParent := AParent;
FSubObjects := TObjectList<TSomeClass>.Create;
//...
end;
destructor TSomeClass.Destroy;
begin
//...
FSubObjects.Free;
inherited Destroy;
end;
procedure TSomeObject.DoSomethingToMakeAChange;
begin
// update FSomethingToBeCounted as needed
Changed;
end;
procedure TSomeClass.SubObjectChanged(ASubObject: TSomeClass);
begin
// update FSomethingToBeCounted as needed, based on which child was changed
Changed;
end;
procedure TSomeClass.Changed;
begin
FHasTheDataChanged := True;
if FParent <> nil then
FParent.SubObjectChanged(Self);
end;