加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

delphi – 程序中的程序?

发布时间:2020-12-15 10:16:41 所属栏目:大数据 来源:网络整理
导读:我发现这个在线代码在程序中有一个过程。 我不明白为什么作者会选择这样写。 我所注意到的是执行的递归函数。 为什么他没有像我看过的大多数代码那样分离过程。 他的实施: procedure XML2Form(tree : TJvPageListTreeView; XMLDoc : TXMLDocument);var iNod
我发现这个在线代码在程序中有一个过程。
我不明白为什么作者会选择这样写。
我所注意到的是执行的递归函数。

为什么他没有像我看过的大多数代码那样分离过程。

他的实施:

procedure XML2Form(tree : TJvPageListTreeView; XMLDoc : TXMLDocument);
var
  iNode : IXMLNode;

  procedure ProcessNode(
    Node : IXMLNode; 
    tn   : TTreeNode);
  var
    cNode : IXMLNode;
  begin
    if Node = nil then Exit;
    with Node do
    begin
      tn := tree.Items.AddChild(tn,Attributes['text']);
      tn.ImageIndex := Integer(Attributes['imageIndex']);
      tn.StateIndex := Integer(Attributes['stateIndex']);
    end;

    cNode := Node.ChildNodes.First;
    while cNode <> nil do
    begin
      ProcessNode(cNode,tn);
      cNode := cNode.NextSibling;
    end;
  end; (*ProcessNode*) 
begin
  tree.Items.Clear;
  XMLDoc.FileName := ChangeFileExt(ParamStr(0),'.XML');
  XMLDoc.Active := True;

  iNode := XMLDoc.DocumentElement.ChildNodes.First;

  while iNode <> nil do
  begin
    ProcessNode(iNode,nil);
    iNode := iNode.NextSibling;
  end;
  XMLDoc.Active := False;
end; (* XML2Form *)


procedure Form2XML(tree: TJVPageListTreeView);
var
  tn : TTreeNode;
  XMLDoc : TXMLDocument;
  iNode : IXMLNode;

  procedure ProcessTreeItem(
    tn    : TTreeNode;
    iNode : IXMLNode);
  var
    cNode : IXMLNode;
  begin
    if (tn = nil) then Exit;
    cNode := iNode.AddChild('item');
    cNode.Attributes['text'] := tn.Text;
    cNode.Attributes['imageIndex'] := tn.ImageIndex;
    cNode.Attributes['stateIndex'] := tn.StateIndex;
    cNode.Attributes['selectedIndex'] := tn.SelectedIndex;

    //child nodes
    tn := tn.getFirstChild;
    while tn <> nil do
    begin
      ProcessTreeItem(tn,cNode);
      tn := tn.getNextSibling;
    end;
  end; (*ProcessTreeItem*)
begin
  XMLDoc := TXMLDocument.Create(nil);
  XMLDoc.Active := True;
  iNode := XMLDoc.AddChild('tree2xml');
  iNode.Attributes['app'] := ParamStr(0);

  tn := tree.TopItem;
  while tn <> nil do
  begin
    ProcessTreeItem (tn,iNode);

    tn := tn.getNextSibling;
  end;

  XMLDoc.SaveToFile(ChangeFileExt(ParamStr(0),'.XML'));
  XMLDoc := nil;
end; (* Form2XML *)

或修改实施:

procedure ProcessNode(Node : IXMLNode; tn : TTreeNode);
var
  cNode : IXMLNode;
begin
  if Node = nil then Exit;
  with Node do
  begin
    tn := tree.Items.AddChild(tn,Attributes['text']);
    tn.ImageIndex := Integer(Attributes['imageIndex']);
    tn.StateIndex := Integer(Attributes['stateIndex']);
  end;

  cNode := Node.ChildNodes.First;
  while cNode <> nil do
  begin
    ProcessNode(cNode,tn);
    cNode := cNode.NextSibling;
  end;
end; (*ProcessNode*)

procedure ProcessTreeItem(tn : TTreeNode; iNode : IXMLNode);
var
  cNode : IXMLNode;
begin
  if (tn = nil) then Exit;
  cNode := iNode.AddChild('item');
  cNode.Attributes['text'] := tn.Text;
  cNode.Attributes['imageIndex'] := tn.ImageIndex;
  cNode.Attributes['stateIndex'] := tn.StateIndex;
  cNode.Attributes['selectedIndex'] := tn.SelectedIndex;

  //child nodes
  tn := tn.getFirstChild;
  while tn <> nil do
  begin
    ProcessTreeItem(tn,cNode);
    tn := tn.getNextSibling;
  end;
end; (*ProcessTreeItem*)

procedure XML2Form(tree : TJvPageListTreeView; XMLDoc : TXMLDocument);
var
  iNode : IXMLNode;
begin
  tree.Items.Clear;
  XMLDoc.FileName := ChangeFileExt(ParamStr(0),nil);
    iNode := iNode.NextSibling;
  end;
  XMLDoc.Active := False;
end;

procedure Form2XML(tree: TJVPageListTreeView);
var
  tn : TTreeNode;
  XMLDoc : TXMLDocument;
  iNode : IXMLNode;
begin
  XMLDoc := TXMLDocument.Create(nil);
  XMLDoc.Active := True;
  iNode := XMLDoc.AddChild('tree2xml');
  iNode.Attributes['app'] := ParamStr(0);

  tn := tree.TopItem;
  while tn <> nil do
  begin
    ProcessTreeItem (tn,'.XML'));
  XMLDoc := nil;
end; (* Form2XML *)

解决方法

这样的嵌套过程在这个XML相关代码中是有意义的。要处理所有节点,需要一个递归调用ProcessNode。你必须注意,有时,内部函数需要访问比一些参数更多的数据。

潜在的实现可能是:

>使用“平”程序,如在您的实现中;
>使用“嵌套”过程,如原来的实现;
>创建一个专用的类(或记录方法),它将保持私有对于该单元的实现部分。

当然,第三个选项听起来更可维护。它将允许清除过程的分离,并允许使用本地方法的变量。使用记录(或旧版本的Delphi对象)将允许处理对象分配在主过程的堆栈上,因此您不需要编写Obj:= TInterType.Create;试试..终于Obj.Free。但是如果你使用一个对象,请注意一些新版本的Delphi has compilation issue – 你应该更好地使用方法记录。

“平面”过程风格是IMHO不比“嵌套”过程更好,更糟糕的是,由于需要向内部调用添加附加参数,或使用一些全局变量。顺便说一下,每次调用都有很多变量会增加堆栈空间,并降低速度。

“嵌套”风格实际上是面向对象的。当调用内部函数时,编译器将寄存器中的调用者堆栈基础传递给嵌套函数(就像对象的附加自参数)。所以内部函数能够访问所有调用者栈变量,就像在私有对象中声明的一样(第三个解决方案)。

Delphi IDE和内部调试器很好地处理嵌套过程。对于一些小的代码(也就是说,在同一个屏幕高度上可以读取的内容),IMHO可能是有意义的。那么,当你需要更多的流程时,具有方法和显式变量的专用记录/对象将更加可维护。但是“平”选项是IMHO不被编码。

我只是written a blog article about these implementation patterns,它将提供QuickSort实现的一些源代码,它将尽可能使用尽可能少的堆栈空间,并且将避免调用过程中的嵌套过程,并改用专用私有对象。

在所有情况下,不要害怕创建一些内部对象/类来实现算法。 Delphi的最新版本甚至允许类定义中的私有类型 – 但是有时候,使内部对象对于单元的实现部分完全是私有的,即使不显示为单元的接口部分的私有成员,我感觉更为舒适。

类不仅用于在单元之外发布过程:OOP也适用于实现模式。您的代码将更加易于维护,在大多数情况下,自身参数将被用于一次性引用所有相关数据,因此您的代码也可能更快更轻!

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读