Today's Delphi Tip of the Day is about resolving "which came first, the chicken or the egg". Because Delphi is a strongly typed language you can't refer to something until it's been defined. However, there are situations where you want to refer to something NOW, but unfortunately it hasn't been defined yet.
In other words "I want the egg of that chicken. I know that chicken hasn't laid that egg yet. However, since I know that chicken is going to lay that egg (trust me I know), let me have that egg now."
This is where forward declarations come into play.
I was brought here by something that came up while reading Pawel Glowacki's book
Expert Delphi. I'm on page 233 from
Chapter 7 - Sensing the world. Pawel discusses the TSensorManager class in the System.Sensors
unit.
There is main TSensorManager class that acts as a gateway to all sensor information. It has a Current: TSensorManager class property that is used to reference all sensor information. At the top of the System.Sensors unit, you can find a TSensoryCategory enumerated type that provides the top level categorization of all possible sensors:
At this point my head was about to explode so I decided to open the
System.Sensors unit and have a look at the actual code Pawel was referring to. Then it hit me.
What the hell is this empty class doing here? How can you have an empty class?
TSensorManager = class;
I remember going down this empty class learning path a while ago. But do you think I can remember what it was, or means. No. Obviously, I had not associated a nice, simple "word picture" to the meaning of this empty class. Because if I had, I would have remembered.
So now I have the nice, easy to remember, "
Oh that's Delphi's way of resolving the chicken or the egg thing" word picture.
Have a look at this type definition snippet from the
System.Sensors unit:"
type
//
//other type declarations
//
TSensorManager = class; //-- egg reference
TCustomSensor = class abstract
public type
TProperty = (UniqueID, Manufacturer, Model, SerialNo, Name, Description);
private
FOnDataChanged: TNotifyEvent;
FOnSensorRemoved: TNotifyEvent;
FOnStateChanged: TNotifyEvent;
FManager: TSensorManager; //-- egg reference
FStarted: Boolean;
//
// other class definitions
//
end;
//
//other type declarations
//
TSensorManager = class abstract //--- chicken reference
public type
TFilters = TDictionary‹string tsensorfilter=""›;
private class var
FCurrentManager: TSensorManager;
class function InternalGetSensorManager: TSensorManager; static;
class constructor Create;
class destructor Destroy;
protected type
TSensorManagerType = class of TSensorManager;
//
// other class definitions
//
end;
//
//other type declarations
//
implementationThe problem arises because there's a private field declaration in the TCustomerSensor class that references the TSensorManager class that doesn't exist yet. It's the damn "chicken or the egg" thing.
To get around this Delphi allows what is called a forward declaration.
This is not by any means the complete class definition. The complete class definition must be declared somewhere inside the same type declarations where the forward declaration resides.
Here are a couple useful links:
http://docwiki.embarcadero.com/RADSt...endent_Classes
http://www.delphibasics.co.uk/RTL.asp?Name=Class
Enjoy!
Semper Fi
Gunny Mike
https://zilchworks.com
Weiterlesen...