views:

192

answers:

3

Ok, this, I'm sure is something simple that is easy to do.

The problem :

I've inherited scary spaghetti code and am slowly trying to better it when new features need adding - generally when a refactor makes adding the new feature neater.

I've got a bunch of code I'm packing into a single unit which, in different places in the application, controls the same physical thing in the outside world. The control appears in several places in the application and operates slightly differently in each instance.

What I've done is to create a unit with all of the features I need which I can simply drop, as a frame, into each form that requires it. Each form then uses the unit's interface methods to customise the behaviour for each instance.

The problem within the problem :

In the unit in question (the frame) I have a variable declared in the IMPLEMENTATION section - local to the unit. I also have a procedure, declared in the TYPE section which takes an argument and assigns that argument to the local variable in question - each form passes a unique variable to each instance of the frame/unit.

What I want it to do is for each instance of the frame to keep its own version of that variable, different from the others, and use that to define how it operates. What seems to be happening, however, is that all instances are using the same value, even if I explicitly pass each instance a different variable.

ie:

Unit FlexibleUnit;
interface
uses
//the uses stuff
type
TFlexibleUnit=class(TFrame)
   //declarations including
   procedure makeThisInstanceX(passMeTheVar:integer);
private
//
public
//
end;

implementation
uses //the uses
var myLocalVar;

procedure makeThisInstanceX(passMeTheVar:integer);
begin
myLocalVar:=passMeTheVar;
end;

//other procedures using myLocalVar 
//etc to the 
end;

Now somewhere in another Form I've dropped this Frame onto the Design pane, sometimes two of these frames on one Form, and have it declared in the proper places, etc. Each is unique in that :

ThisFlexibleUnit : TFlexibleUnit;
ThatFlexibleUnit : TFlexibleUnit;

and when I do a:

ThisFlexibleUnit.makeThisInstanceX(var1); //want to behave in way "var1"
ThatFlexibleUnit.makeThisInstanceX(var2); //want to behave in way "var2"

it seems that they both share the same variable "myLocalVar".

Am I doing this wrong, in principle? If this is the correct method then it's a matter of debugging what I have (which is too huge to post) but if this is not correct in principle then is there a way to do what I am suggesting?

Thanks in advance, Stack Overflow - you guys (and gals!) are legendary.

EDIT:

Ok, so the lesson learned here is that the class definition ends after its private/public declarations and that all objects which are instances of the class(es) within the unit share the one and only instance of everything in the implementation section of the unit.

Delphi units are like Mr. Potato Head.

+1  A: 

You are calling the makeThisInstanceX method as a class (static) method rather than creating an instance of the class and calling it as an object method. Take a look at this reference:

http://oreilly.com/catalog/delphi/chapter/ch02.html

David M
Ah, crap - so I do a ThisFlexibleUnit:=TFlexibleUnit.Create, yes? I suppose I could even pass vars through a custom Create method - do the initializing that way? I'm a poor LabView veteran...still getting used to this OOP stuff.
Justin
Ah, actually, Jason nailed it. I figured right that adding to the design pane does an implicit Create for the object - just still learning the ropes with the whole public/private thing.
Justin
+7  A: 

myLocalVar is a global variable, but only visible within the unit.

A local variable would be in a procedure/function, like

procedure makeThisInstanceX(passMeTheVar: integer);
var
  myLocalVar: Integer;
begin
  myLocalVar := passMeTheVar;
end;

if you want an instance variable, that is each frame has its own copy, put it in the class:

type
  TFlexibleUnit = class(TFrame)
     procedure makeThisInstanceX(passMeTheVar:integer);
  private
    myLocalVar: Integer;
  ...
  end;
jasonpenny
Ah, genius - I understand now. Variables in implementation are local to the class but global to its instances. Things in private are local to the instance.Things in public are global to everything.Yes?This works. Thanks, Jason.
Justin
Or am I totally screwing up the terminology - would you consider anything "global" outside of a procedure or function block, even with so many levels of scope to be global to? Would "private global" be a better term for this type of variable?
Justin
Justin, please note that *variables* declared at unit scope have absolutely no relation whatsoever to *classes* declared at unit scope. You might be confusing things with Java, where everything belongs to a class, and there's only one class per source file. In Delphi, neither of those things is true.
Rob Kennedy
Variables in the implementation section are local to the *unit* but global to all the code inside the unit. It has nothing to do with classes or instances, since Delphi isn't a "pure" object-oriented language.
Mason Wheeler
@ Mason - yes, I'm slowly figuring that out, haha. @ Rob - Yes, that's a key point and it makes many things make a lot more sense. I'm not a java programmer, mind you - I'm not really a programmer at all. I come from ten years of LabView and have moved recently to Delphi with a new employer. My understanding of OOP is probably very idealistic and academic, which is likely why it best fits Java's model. The last time I used Pascal was over a decade ago - and as plain vanilla Pascal at that, so I'm still cutting my teeth on Delphi's new-age goodies.Thanks both - great comments!
Justin
A: 

frame / unit / class / control

I applaud your heroic attempt to better the code. However, judging by your questions and comments I regret to inform you that your understanding is very limited.

A frame is not a unit which is not a class. A frame is a class but not every class is a frame. A frame is a control but not every control is a frame. Units have interface and implementation (and initialization and finalization) sections. Classes have private and public (and protected and published) parts.

I did not put the last paragraph in to try to teach but to allow you to gauge your understanding level. A Delphi developer ought to have no problem with the paragraph. I'm not trying to make you feel bad or to show off - just trying to help. Perhaps Stack Overflow is not the right tool for you at this time.

As somebody just learning Delphi for the first time, I might be confused by some of the seemingly redundant features. But the product has a long history and each addition made sense at the time it was added. It was also easier to learn when you only had to learn it a piece at a time.

Pete R.
I'm well aware of what I do and don't know, Pete, thanks. That's why I asked the question. My expertise is in control systems and instrumentation - I'm new to Delphi. I'd never even looked at a line of Delphi code until six weeks ago. I've got a stack of Cantu's books on my desk and none of them explained the nuts and bolts of things as well as the answers I just got here (save yours, of course), so I'll correct you in saying that StackOveflow was an excellent tool. With any luck, perhaps this post will be useful to others as well.
Justin
And, since we're being passive aggressive, I'll suggest that if you're planning to be as helpful as this that Stack Overflow is probably not the right tool for YOU. Cheers!
Justin
@Pete:SO is the right place for everyone who's got a programming problem of any kind. I don't like to downvote, but I don't see how demotivating and sending the OP away from this site is helpful to anyone, sorry.
Wouter van Nifterick
-1 as it is not an answer, and for same reasons as upper.Just be cool !
TridenT
I'm sorry that I came across as passive aggressive. I assure you that was not my intent. Since you could not hear my spoken voice let alone see my face and body language you had to evaluate my emotions solely from my written words. (Maybe I should have tried some emoticons.) I am, however, more convinced than ever that SO is a limited tool. It does allow information exchange, but, as the comments show, it doesn't always convey emotion correctly.
Pete R.