Description |
The Class keyword is the central part of Object Oriented code. It starts the definition of literally a 'class' of object types.
This definition contains so-called 'members' - data and methods (subroutines). When an object of the class is created, it is a stand alone item - you can access the data and methods of the object independently of any other object. It is like a Delphi record, but with active components - methods.
These elements are defined in the class type definition. The method elements are implemented in the implementation section of the Unit.
A class declaration has this typical basic layout :
type
className = class(BaseClass)
private
// Data/method defs local to this Unit
protected
// Data/method defs local to this class + descendants
public
// Data/method defs usable with all objects of this class
published
// Externally interrogatable public definitions
end;
Parameters can be passed when creating an object instance of a class. These are passed to the Constructor method of the class. The word constructor is used instead of function or method. You may have a number of constructors for different parameter sets. These are supplied with the overload; keyword after the end of the constructor definition.
Normally, the constructor method name is Create.
See the code for an example.
When an object is destroyed, the Destructor method is called. You can use this to take special action before the object storage is reclaimed.
Normally, the destructor method name is Destroy.
There are a number of uses of the word Class:
1.
A class definition based on the TObject class by default. All classes must be based on another class, with TObject being the default, highest level class. TObject provides rudimentry functionality - you would normally define all of the data and methods yourself, and use none from TObject.
Within the definitions of a Class, you can prefix function or procedure definitions with the Class keyword. This allows the subroutine to be called from the Class itself in addition to an object instance of the class. Because a class is not a real object, it has no storage allocated to data. So a Class subroutine must operate without reference to internal class data.
2.
Class definition based on a specified class but with no local additions or changes. You have a new class that acts identically to the BaseClass
3.
Forward class declaration. It allows all classes in a Unit to be listed at the start of the type section. So this is a matter of convenience rather than anything else.
4.
Class definition based on a specified class. As 1 above, but you can specify which class you are basing your new class on. Your class will again be a mixture of ancestor and local declarations.
5.
A class can contain implementations of externally predefined interfaces.
6.
A metaclass reference allows a variable to be used to reference a class rather than an object.
|
|
Notes |
The optional packed keyword tells Delphi to minimise storage taken by the class. It stops aligning data on 2, 4 or 8 byte boundaries, normally done for performance reasons.
|
|
Related commands |
Constructor |
|
Defines the method used to create an object from a class |
Interface |
|
Used for Unit external definitions, and as a Class skeleton |
Object |
|
Allows a subroutine data type to refer to an object method |
Private |
|
Starts the section of private data and methods in a class |
Property |
|
Defines controlled access to class fields |
Protected |
|
Starts a section of class private data accesible to sub-classes |
Public |
|
Starts an externally accessible section of a class |
Published |
|
Starts a published externally accessible section of a class |
TObject |
|
The base class type that is ancestor to all other classes |
Virtual |
|
Allows a class method to be overriden in derived classes |
Dynamic |
|
Allows a class method to be overriden in derived classes |
|
|
|
Example code : A Unit with 2 class definitions and code that uses both |
// Full Unit code. // ----------------------------------------------------------- // You must store this code in a unit called Unit1 with a form // called Form1 that has an OnCreate event called FormCreate.
unit Unit1;
interface
uses
SysUtils, Forms, Dialogs;
type // Define the classes in this Unit at the very start for clarity TForm1 = Class; // This is a forward class definition
TFruit = Class(TObject) // This is an actual class definition : // Internal class field definitions - only accessible in this unit
private
isRound : Boolean;
length : single;
width : single;
diameter : single; // Fields and methods only accessible by this class and descendants
protected // Externally accessible fields and methods
public // 2 constructors - one for round fruit, the other long fruit
constructor Create(diameter : single); overload;
constructor Create(length : single; width : single); overload; // Externally accessible and inspectable fields and methods
published // Note that properties must use different names to local defs
property round : Boolean
read isRound;
property len : single
read length;
property wide : single
read width;
property diam : single
read diameter; end; // End of the TFruit class definition
// The actual TForm1 class is now defined
TForm1 = Class(TForm)
procedure FormCreate(Sender: TObject);
procedure ShowFruit(fruit : TFruit);
private // No local data
public // Uses just the TForm ancestor class public definitions
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
// Create a round fruit object
constructor TFruit.Create(diameter: single);
begin // Indicate that we have a round fruit, and set its size
isRound := true;
self.diameter := diameter;
end;
// Create a long fruit object
constructor TFruit.Create(length, width: single);
begin // Indicate that we have a long fruit, and set its size
isRound := false;
self.length := length;
self.width := width;
end;
// Form object - action taken when the form is created
procedure TForm1.FormCreate(Sender: TObject);
var
apple, banana : TFruit;
begin // Let us create our fruit objects
apple := TFruit.Create(3.5);
banana := TFruit.Create(7.0, 1.75);
// Show details about our fruits
ShowFruit(apple);
ShowFruit(banana);
end;
// Show what the characteristics of our fruit are
procedure TForm1.ShowFruit(fruit: TFruit);
begin
if fruit.round
then WriteLn('We have a round fruit, with diam = '+
FloatToStr(fruit.diam))
else
begin
WriteLn('We have a long fruit');
WriteLn(' it has length = '+FloatToStr(fruit.len));
WriteLn(' it has width = '+FloatToStr(fruit.wide));
end;
end;
end.
|
We have a round fruit with diam = 3.5
We have a long fruit
it has a length = 7
it has a width = 1.75
|
|