As there is no garbage collection in Delphi, where exactly do you unload variables?
Say I have a type with a set of private vars. Would it suffice to have a Destroy method that does this work? Do I need to explicitly call this destroy method in m开发者_如何学Goy consuming classes?
The best way to organize destruction in delphi is to always think about "who will create the given vars".
If you also free them in this context (For you private vars the destroy method of the class) it's much less likely that you will encounter memory leaks.
Actually the destructor of a class is normally not called via
myInstance.Destroy();
instead the typical way of doing it is via
FreeAndNil(myInstance);
or
myInstance.Free();
As delphi will handle calling the destructor method at order
Objects need to be destroyed when you are ready with them: using .Free (which calls the destructor .Destroy) or FreeAndNil.
If you are using interfaces: they are reference counted and hence they are freed for you. The same for strings.
Most functions that you need to pass an object do not take ownership of the object so you should free it afterwards when you are done with them. If you create components on a form, please note that they are objects, are owned by the form and you should let the form free them for you.
For example: in your TLight you create a TTimer probably without an owner. In this case you should Free the timer in the destructor of the TLight class. If your TLight was a TControl or TComponent itself you could have created the Timer with Self as the Owner and it was automatically freed when your TLight instance was freed.
That's how I see it:
Primitive types (like integer, real, double, extended), arrays, sets, records: they are automatically destroyed when out of scope.
Reference-counted types (strings, interfaces types, interface references): they are automatically destroyed when their reference counter is equal to zero.
Objects from classes that fall in one of those situations: does not descend from TComponent, are in list objects that do not implement ownership or are a TComponent descendant but does not have an owner assigned to it:
- When their class descend from TInterfacesObject and are accessed from a interface reference: same behavior from reference-counter types (see above)
- Other cases: call Object.Free or FreeAndNil(Object) to manually destroy it (in a try..finally structure would be even better)
Objects that have an owner (TComponent descendants or are in list objects that implement ownership): the owner will take of them in proper time.
I noticed the following comment from OP:
I have noticed the concept of owner. Yet I couldn't pass my custom class to the TTimer.Create() method as it is expecting a TComponent. Why do they restrict things to be used in forms only? Doesn't that furhter petrify the bad habit of putting logic in your views (forms)?
See, a TComponent descendant can be registered on the pallete to have the ability to be used in design-time (for example, in a form) . But it's doesn't means it must!! You can pass your custom-class to TTimer.Create() if it descends from TComponent but you don't need to instantiate it in design-time - or even be owned by a TForm descendant (if you want to manage it's lifetime, you don't even need an owner!).
Ownership is a mechanism it's to help people to save time....
You keep referring to a "type with private vars" and asking about "unloading variables." I'm going to go out on a limb (as I may be have misinterpreted your message), and presume you're talking about class variables and are asking about when these class variables should be finalized when the "class unloads." (You've been doing Java or .NET programming at some point, no ;-).
The key to what you're asking is a unit finalization section. The overall layout of a unit includes 4 overall sections, two of which are optional, initialization and finalization.
unit Foo;
interface
// put things here you want other units to see
implementation
// put the *implementation* of the things from the interface here along with things
// you only want this unit to see.
initialization
// <optional> put code here that you want to execute when this unit is "loaded"
finalization
// <optional> put code here that you want to execute when this unit is "unloaded"
end.
If you're talking about instance variables of a class type, then some of the other answers you've already gotten (and are bound to get) should shed some light on that.
精彩评论