在不同的Delphi函数中使用对象

时间:2012-12-12 10:32:08

标签: delphi class object delphi-2010

这只是一个非常简单的问题,我无法找到一个明确的答案。我没有足够的时间阅读所有文档,因为我正处于紧张状态。

但现在是。

我已经在我的TForm类之上创建了一个新类:

 Bucket = Class
   glass: Integer;
   steel: Integer;
 End;

然后我在属于TForm1

的方法中创建了几个对象
procedure TForm1.getMarbles;
var
  objPlastic: Bucket;
  objAlu: Bucket;

begin
  // Initialize objects
  objPlastic := Bucket.Create;
  objAlu := Bucket.Create;

  // Get Values from edtBox
  val(Edit1.Text, objPlastic.steel, code);
  val(Edit2.Text, objAlu.steel, code);
  val(Edit3.Text, objPlastic.glass, code);
  val(Edit4.Text, objAlu.glass, code);
end; 

我的问题是我不知道如何在其他方法中使用这些对象。到目前为止,我尝试用我想要使用的其他方法中的各种方式来定义它们,但是我无法让它工作。

以下是方法及其当前设置的方法(始终返回0):

procedure TForm1.marbleDrop(kind: string);
var
  objPlastic: Bucket;
  I: Integer;
begin
  objPlastic := Bucket.Create;
  if kind= 'plastic' then // the function is receiving this parameter
  begin
    for I := 0 to objPlastic.glass do
    begin
      showmessage(inttostr(objPlastic.glass)); //returns 0
    end;
  end;

end;

对不起这类问题,但我找不到更好的方法。

顺便说一下,这是我正在使用的代码的简化版本。我尽力摆脱任何错别字,因为它是我实际使用的翻译,但它主要是关于这个想法。我在delphi中的代码中没有拼写错误。

2 个答案:

答案 0 :(得分:5)

另一方面,要跨方法访问对象,您必须:

  1. 将对象声明为Form类的成员:

    type
      TForm1 = class(TForm);
      ...
      private
        objPlastic: Bucket;
        objAlu: Bucket;
      ...
      end;
    
    procedure TForm1.getMarbles;
    begin
      // Initialize objects
      if objPlastic = nil then objPlastic := Bucket.Create;
      if objAlu = nil then objAlu := Bucket.Create;
    
      // Get Values from edtBox
      objPlastic.steel := StrToIntDef(Edit1.Text, 0);
      objAlu.steel := StrToIntDef(Edit2.Text, 0);
      objPlastic.glass := StrToIntDef(Edit3.Text, 0);
      objAlu.glass := StrToIntDef(Edit4.Text, 0);
    end;
    
    procedure TForm1.marbleDrop(kind: string);
    begin
      if (kind = 'plastic') and (objPlastic <> nil) then
      begin
        ShowMessage(IntToStr(objPlastic.glass));
      end;
    end;
    
  2. 将它们作为方法本身的参数传递:

    procedure TForm1.getMarbles(objPlastic, objAlu: Bucket);
    begin
      // Get Values from edtBox
      if objPlastic <> nil then
      begin
        objPlastic.steel := StrToIntDef(Edit1.Text, 0);
        objPlastic.glass := StrToIntDef(Edit3.Text, 0);
      end;
      if objAlu <> nil then
      begin
        objAlu.steel := StrToIntDef(Edit2.Text, 0);
        objAlu.glass := StrToIntDef(Edit4.Text, 0);
      end;
    end;
    
    procedure TForm1.marbleDrop(objWhichKind: Bucket);
    begin
      if objWhichKind <> nil then
      begin
        ShowMessage(IntToStr(objWhichKind.glass));
      end;
    end;
    
    procedure TForm1.someMethod();
    var
      objPlastic: Bucket;
    begin
      objPlastic := Bucket.Create;
      getMarbles(objPlastic, nil);
      marbleDrop(objPlastic);
      objPlastic.Free;
    end;
    

答案 1 :(得分:1)

当然它返回零。这是另一个目标。您应该在传递任何其他参数变量时传递它。你所做的与

类似
procedure TForm1.Drop1(kind: string);
begin
   marbleDrop(); // here kind = "staal"
end;

procedure TForm1.marbleDrop();
var
  kind: string;
begin
  if kind = 'plastic' then // it is not !!! why ???
  begin
....
  end;
end;

您还有另一个问题 - Memory leak

  val(Edit4.Text, objAlu.glass, code);
end; 

您刚刚创建了两个对象 - 并为它们分配了Heap memory。 但是你没有释放他们。这就是剩下的垃圾,它会增长,增长和增长 - 直到程序耗尽所有Windows内存并被杀死。

如果你想在没有任何准确性的情况下使用内存而不“浪费”你的思考和学习时间 - 你最好使用在虚拟机中运行的一些托管语言,如PHP,Python,Java和其他基于JVM的C#,和其他.NEt-based。

要制作好的Delphi代码,您至少应该了解CPU的作用和原因。


特别是在您的代码中,您最好

  1. 使用记录而不是类
  2. 将其作为const-var-参数传递,以避免冗余复制。
  3. 就像那样:

    type TBucket = Record  glass, steel: Integer; End;
    type TForm1 = class (TForm) 
         .....
     private
       var objPlastic, objAlu: TBucket;
        (* making variables more global: now they are form-local not function-local *)
    ......
    
    procedure TForm1.getMarbles;
    begin
       objPlastic.steel := StrToIntDef(Edit1.Text, 0);
       objAlu.steel := ...
       Self.objPlastic.glass ...  (* adding Self - just for clarity where those variable are taken from *)
       Self.objAlu.glass ....
    end; 
    
    procedure TForm1.marbleDrop(kind: string);
    var
      I: Integer;
    begin
      if kind = 'plastic' then // the function is receiving this parameter
      begin
        for I := 0 to Self.objPlastic.glass do
        begin
          showmessage(inttostr(objPlastic.glass)); 
            //getting via common parent context - TForm1 object, referenced as Self pseudo-variable
          marbleTell(objPlastic); // passing as parameter
        end;
      end;
    end;
    
    procedure TForm1.marbleTell(const arg: TBucket);
    // do not forget to use const to pass variable by-reference not by-value
    begin
       showmessage(inttostr(arg.glass)); // getting via argument
    end;