1

I'm doing a simple class definition in Delphi and I wanted to use a TStringList in the class & it's constructor (so everytime you create an object, you pass it a StringList and it does some magic stuff to the StringList data, copying the string list to it's own internal string list). The problem I get is that when I try to declare what it "uses" before the class definition (so it knows how to handle the TStringList), it fails on compile. But without that, it doesn't know what a TStringList is. So it seems to be a scoping issue.

Below is a (very simplified) class definition, similar to what I'm trying to do. Can someone suggest how I can make this work and get the scoping right?

I tried adding the uses statements at the project level as well, but it still fails. I wonder what I need to do to get this right.

unit Unit_ListManager;

interface

type
TListManager = Class

private
  lmList   : TStringList;
  procedure SetList;


published
  constructor Create(AList : TStringList);
end;

implementation

uses
  SysUtils,
  StrUtils,
  Vcl.Dialogs;

  constructor TBOMManager.Create(AList : TStringList);
  begin
    lmList := TStringList.Create;
    lmList := AListList;
  end;

  procedure SetPartsList(AList : TStringList);
  begin
     lmList := AListList;
     ShowMessage('Woo hoo, got here...');
  end;
end.

Kind Regards

JoeBilly
  • 3,057
  • 29
  • 35
DoubleE
  • 71
  • 1
  • 10
  • Don't forget the `inherited` statement in the constructor. – LU RD Nov 03 '13 at 19:41
  • @LURD is that even necessary when no parent type is defined? – LaKraven Nov 03 '13 at 19:43
  • 1
    @LaKraven, strictly no, but hard to find errors can arise as soon as the base class is changed. I would not allow this in my codebase. – LU RD Nov 03 '13 at 19:45
  • @LURD that's a good point... I'll update my answer to account for that possibility :) – LaKraven Nov 03 '13 at 19:46
  • If you don't want to have only a reference to the external Stringlist(that's what I understood from your create) you must not use `lmList := AListList;` but `assign` e.g. `constructor TListManager.Create(AList: TStringList); begin inherited Create; FlmList := TStringList.Create; SetList(AList); end; procedure TListManager.SetList(AList : TStringList); begin FlmList.Assign(AList); end;` – bummi Nov 03 '13 at 19:52
  • Disagree with the -1 so... +1 – LaKraven Nov 03 '13 at 22:14

1 Answers1

1

You didn't show where exactly you were adding the unit reference, but I'm betting it was the wrong place. Take note of the additional code between interface and type.

I've also corrected your definition of the constructor, which you had placed in published instead of public. Only property items belong in the published section.

unit Unit_ListManager;

interface

uses
  Classes,
  SysUtils,
  StrUtils,
  Vcl.Dialogs;    

type
TListManager = Class
private
  lmList   : TStringList;
  procedure SetList;    
public
  constructor Create(AList : TStringList);
end;

implementation

constructor TListManager.Create(AList : TStringList);
begin
  inherited Create; // This way, if the parent class changes, we're covered!
  // lmList := TStringList.Create; This would produce a memory leak!
  lmList := AListList;
end;

procedure TListManager.SetList;
begin
// You never provided an implementation for this method
end;

end.
LaKraven
  • 5,804
  • 2
  • 23
  • 49
  • Umm, this seems to reproduce the inconsistency in the constructor (TListManager v. TBOMManager) in the OP's q. – MartynA Nov 03 '13 at 19:42
  • @MartynA I missed that one... thanks for pointing it out, I've corrected it now :) – LaKraven Nov 03 '13 at 19:42
  • Ahh thank you! There was some renaming I had done when I copied what I was working on. That explains List v BOM manager. You are right, I had that scoping wrong. Thanks for the help with this, it compiles now! – DoubleE Nov 03 '13 at 19:45
  • In the future, @DoubleE, it is very helpful if you post the content of the warning/error messages in with your question... this makes it easier for us to rapidly locate the problem and provide a solution :) Please don't forget to mark this answer as correct :) – LaKraven Nov 03 '13 at 19:48
  • this: `lmList := TStringList.Create; lmList := AListList;` does not make much sense ;-). Maybe he is searching for assign .... – bummi Nov 03 '13 at 19:53
  • You are leaking a stringlist. `lmList := AListList` will overwrite the internally created list. – LU RD Nov 03 '13 at 19:53
  • `lmList.Text := AList.Text` will make a local copy if that is what the OP wants. – LU RD Nov 03 '13 at 19:54
  • You probably want a destructor as well so you can free the stringlist. – Keith Miller Nov 03 '13 at 19:56
  • Updated the answer to remove the silly memory leak (which, again, I didn't initially notice). No point in creating a fresh instance and having to manage that when passing a reference is sufficient! – LaKraven Nov 03 '13 at 20:01