Difference between revisions of "Class"

From Lazarus wiki
Jump to navigationJump to search
m (remove chunk headlines)
(link: extended class syntax)
 
(6 intermediate revisions by 4 users not shown)
Line 1: Line 1:
 
{{Class}}
 
{{Class}}
  
A '''class''' is a highly structured data [[Type|type]] in Object [[Pascal]] dialects such as Delphi or the [[Mode ObjFPC|ObjFPC]] dialect. Classes are able to contain [[Variable|variables]], [[constructor]]s, [[destructor]]s, [[Function|function]]s, [[Procedure|procedures]], and [[Property|properties]] using access scopes.
+
A '''class''' is a highly structured data [[Type|type]] in Object [[Pascal]] dialects such as [[Mode Delphi|Delphi]] or the [[Mode ObjFPC|ObjFPC]] dialect. Classes are able to contain [[Variable|variables]], [[Constructor|constructors]], [[Destructor|destructors]], [[Function|functions]], [[Procedure|procedures]], and [[Property|properties]] using access scopes.
  
Classes are able to inherit and to be inherited by other classes. For run-time purposes, any class not specifying a parent class automatically inherits from [[TObject]], as it has required components for all classes. Because of TObject's dependency, any [[subclass]]'s destructor must have the [[override]] directive. Additionally, any of your class's constructors must specify [[Inherited|inherited]] in their body. A class can have several constructors, but only one destructor.
+
Classes are able to inherit and to be inherited by other classes. For [[runtime|run-time]] purposes, any class not specifying a parent class automatically inherits from [[TObject]], as it has required components for all classes. Because of TObject's dependency, any [[subclass]]'s destructor must have the [[override]] directive. Additionally, any of your class's constructors must specify [[Inherited|inherited]] in their body. A class can have several constructors, but only one destructor.
  
 
Object Pascal does not support multiple inheritance: apart from the implicit inheritance by TObject, classes can have only one ancestor class. Polymorphism is implemented with method directives. Here is a simple class declaration; let's explain it.
 
Object Pascal does not support multiple inheritance: apart from the implicit inheritance by TObject, classes can have only one ancestor class. Polymorphism is implemented with method directives. Here is a simple class declaration; let's explain it.
  
<syntaxhighlight>
+
<syntaxhighlight lang="pascal">
 
type
 
type
    TMyClass = class
+
  TMyClass = class
    private
+
  private
        FSomeVar: Integer;
+
    FSomeVar: integer;
    public
+
  public
        constructor Create; overload;
+
    constructor Create; overload;
        constructor Create(Args: array of Integer); overload;
+
    constructor Create(Args: array of integer); overload;
        destructor Destroy; override;
+
    destructor Destroy; override;
        function GetSomeVar: Integer;
+
    function GetSomeVar: integer;
        procedure SetSomeVar(newvalue: Integer);
+
    procedure SetSomeVar(newvalue: integer);
    published
+
  published
        property SomeVar: Integer read GetSomeVar write SetSomeVar default 0;
+
    property SomeVar: integer read GetSomeVar write SetSomeVar default 0;
    end;
+
  end;
 
</syntaxhighlight>
 
</syntaxhighlight>
  
Between the keywords 'class' and 'end' we find members declarations, both variables and methods. Some methods (functions and/or procedures) are preceded by scope modifiers ('''private''', '''public''', '''published''') and followed by directives ('''overload''', '''override''') and a strange '''property''' thing. Let's explain them all.
+
Between the keywords 'class' and 'end' we find member declarations, both variables and methods. Some methods (functions and/or procedures) are preceded by scope modifiers ('''private''', '''public''', '''published''') and followed by directives ('''overload''', '''override''') and a strange '''property''' thing. Let's explain them all.
  
 
==Notes on inheritance==
 
==Notes on inheritance==
In Object Pascal, derived classes inherits all members of the base class, even those not overloaded with the same name. Example:
+
In Object Pascal, derived classes inherit all members of the base class, even those not overloaded with the same name. Example:
  
<syntaxhighlight>
+
<syntaxhighlight lang="pascal">
 
type
 
type
//base class
+
  //base class
MyClass = class
+
  MyClass = class
  procedure Proc1;   
+
    procedure Proc1;   
end;
+
  end;
  
//derived class
+
  //derived class
YourClass = class(MyClass)   
+
  YourClass = class(MyClass)   
  procedure Proc1; //same name of MyClass procedure
+
    procedure Proc1; //same name of MyClass procedure
end;
+
  end;
  
 
var
 
var
   a:MyClass;
+
   a: MyClass;
   b:YourClass;
+
   b: YourClass;
 
begin
 
begin
   a:=MyClass.Create;
+
   a := MyClass.Create;
   b:=YourClass.Create;
+
   b := YourClass.Create;
 
   a.Proc1;          // uses procedure in MyClass  
 
   a.Proc1;          // uses procedure in MyClass  
 
   b.Proc1;          // uses procedure in YourClass
 
   b.Proc1;          // uses procedure in YourClass
Line 63: Line 63:
 
==Properties==
 
==Properties==
  
A property is a variable that is accessed through methods. The variable SomeVar in the example above will be read and written in the code like a simple variable, but under the hood the compiler will call the methods specified in the property declaration. This allows to calculate it on the fly, or run boundary checks, input validation, formatting or just a placeholder for future extensions. Some rules apply:
+
A property is a variable that is accessed through methods. The variable SomeVar in the example above will be read and written in the code like a simple variable, but under the hood the [[Compiler|compiler]] will call the methods specified in the property declaration. This allows to calculate it on the fly, or run boundary checks, input validation, formatting or just a placeholder for future extensions. Some rules apply:
  
 
* Either read or write methods, at least one of them, must be present;
 
* Either read or write methods, at least one of them, must be present;
Line 72: Line 72:
 
'''default''' sets a starting value for the property: it's optional and can be omitted. Another option is '''stored false''':  
 
'''default''' sets a starting value for the property: it's optional and can be omitted. Another option is '''stored false''':  
  
<syntaxhighlight>
+
<syntaxhighlight lang="pascal">
        property SomeVar: Integer read GetSomeVar write SetSomeVar stored false;
+
property SomeVar: Integer read GetSomeVar write SetSomeVar stored false;
 
</syntaxhighlight>
 
</syntaxhighlight>
  
Line 80: Line 80:
 
==self==
 
==self==
  
The '''self''' argument is passed by default to every (non static) method: it's an alias to the specific class instance which the method belongs to. This way every class can identify itself and have access to its members without ambiguity.
+
The '''[[Self|self]]''' argument is passed by default to every (non static) method: it's an alias to the specific class instance which the method belongs to. This way every class can identify itself and have access to its members without ambiguity.
  
 
==Method directives==
 
==Method directives==
Line 86: Line 86:
  
 
=== virtual, dynamic, override ===
 
=== virtual, dynamic, override ===
these three directives are mutually exclusive. '''virtual''' means that the method can be overwritten by the derived class. '''dynamic''' means the same thing, but the implementation differs: virtual members addresses are stored in a table, while dynamic members does not use tables and does not occupy RAM, but their resolution mechanism is slower.
+
these three directives are mutually exclusive. '''virtual''' means that the method can be overwritten by the derived class. '''dynamic''' means the same thing, but the implementation differs: virtual members addresses are stored in a table, while dynamic members do not use tables and do not occupy RAM, but their resolution mechanism is slower.
  
 
A derived class can implement its own version of a virtual method, but the base method is still available; if the new method is marked '''override''' it hides the base virtual method, which cannot be called anymore. This holds true in case of dynamic methods, too. However you cannot override a method if it's not virtual or dynamic.
 
A derived class can implement its own version of a virtual method, but the base method is still available; if the new method is marked '''override''' it hides the base virtual method, which cannot be called anymore. This holds true in case of dynamic methods, too. However you cannot override a method if it's not virtual or dynamic.
Line 97: Line 97:
  
 
===overload===
 
===overload===
<syntaxhighlight>
+
<syntaxhighlight lang="pascal">
        function MultiSum(a, b : Integer): Integer; overload;
+
function MultiSum(a, b: integer): integer; overload;
        function MultiSum(a, b : AnsiString): AnsiString; overload;
+
function MultiSum(a, b: AnsiString): AnsiString; overload;
 
</syntaxhighlight>
 
</syntaxhighlight>
 
With the '''overload''' directive you can declare many methods - functions or procedures - with the same name but different type and parameters.
 
With the '''overload''' directive you can declare many methods - functions or procedures - with the same name but different type and parameters.
  
<syntaxhighlight>
+
The class needs the constructor to be implemented in the implementation section of the unit:
var
 
    classInstance: TMyClass.Create;
 
</syntaxhighlight>
 
but if you declare the variable as a class without initialization of the object and you want create the object dynamically you need to do:
 
<syntaxhighlight>
 
var
 
    classInstance: TMyClass;
 
  
 +
<syntaxhighlight lang="pascal">
 
implementation
 
implementation
 +
 +
constructor TMyClass.Create;
 
begin
 
begin
    classInstance := TMyClass.Create;
+
  inherited;
 +
  SomeVar := 6;
 
end;
 
end;
 +
 +
end.
 
</syntaxhighlight>
 
</syntaxhighlight>
  
<syntaxhighlight>
+
The destructor and all procedures and functions of the class must also be implemented in the implementation section.
constructor TMyClass.Create;
+
 
 +
Instances of the class can then be declared as variables:
 +
 
 +
<syntaxhighlight lang="pascal">
 +
var
 +
  classInstance: TMyClass;
 +
</syntaxhighlight>
 +
 
 +
Before using an instance, it must be created with:
 +
 
 +
<syntaxhighlight lang="pascal">
 
begin
 
begin
   inherited;
+
   classInstance := TMyClass.Create;
   SomeVar := 6;
+
   ...
 
end;
 
end;
 
</syntaxhighlight>
 
</syntaxhighlight>
 +
 +
== Classes compared to other structured types ==
 +
{{Template:Object Types}}
 +
 +
=== See also ===
 +
[[extended class syntax]] Examples
  
 
{{Data types}}
 
{{Data types}}

Latest revision as of 02:07, 12 February 2022

Deutsch (de) English (en) français (fr) русский (ru)

A class is a highly structured data type in Object Pascal dialects such as Delphi or the ObjFPC dialect. Classes are able to contain variables, constructors, destructors, functions, procedures, and properties using access scopes.

Classes are able to inherit and to be inherited by other classes. For run-time purposes, any class not specifying a parent class automatically inherits from TObject, as it has required components for all classes. Because of TObject's dependency, any subclass's destructor must have the override directive. Additionally, any of your class's constructors must specify inherited in their body. A class can have several constructors, but only one destructor.

Object Pascal does not support multiple inheritance: apart from the implicit inheritance by TObject, classes can have only one ancestor class. Polymorphism is implemented with method directives. Here is a simple class declaration; let's explain it.

type
  TMyClass = class
  private
    FSomeVar: integer;
  public
    constructor Create; overload;
    constructor Create(Args: array of integer); overload;
    destructor Destroy; override;
    function GetSomeVar: integer;
    procedure SetSomeVar(newvalue: integer);
  published
    property SomeVar: integer read GetSomeVar write SetSomeVar default 0;
  end;

Between the keywords 'class' and 'end' we find member declarations, both variables and methods. Some methods (functions and/or procedures) are preceded by scope modifiers (private, public, published) and followed by directives (overload, override) and a strange property thing. Let's explain them all.

Notes on inheritance

In Object Pascal, derived classes inherit all members of the base class, even those not overloaded with the same name. Example:

type
  //base class
  MyClass = class
    procedure Proc1;   
  end;

  //derived class
  YourClass = class(MyClass)  
    procedure Proc1; //same name of MyClass procedure
  end;

var
  a: MyClass;
  b: YourClass;
begin
  a := MyClass.Create;
  b := YourClass.Create;
  a.Proc1;          // uses procedure in MyClass 
  b.Proc1;          // uses procedure in YourClass
  MyClass(b).Proc1; // uses procedure in MyClass

Scope modifiers

Scope modifiers tell the compiler who can call a method:

  • private: the member can be called/accessed only by other methods in the same class;
  • public: the member can be called/accessed by any other part of the program;
  • protected: the member can be called/accessed from other classes in the same unit and from derived classes, but not from further derivated classes.
  • published: the variable is public, and it will appear in the IDE's Object Inspector.

Scope modifiers cannot be changed in derived classes: members will maintain their visibility (or lack thereof) forever, everywhere.

Properties

A property is a variable that is accessed through methods. The variable SomeVar in the example above will be read and written in the code like a simple variable, but under the hood the compiler will call the methods specified in the property declaration. This allows to calculate it on the fly, or run boundary checks, input validation, formatting or just a placeholder for future extensions. Some rules apply:

  • Either read or write methods, at least one of them, must be present;
  • The read method (if present) cannot have parameters;
  • The write method (if present) must have exactly one parameter;
  • Both read and write methods cannot be dynamic: if they are virtual they cannot be overload.

default sets a starting value for the property: it's optional and can be omitted. Another option is stored false:

property SomeVar: Integer read GetSomeVar write SetSomeVar stored false;

This way the write method will be called, but the value will NOT be saved in the variable.

self

The self argument is passed by default to every (non static) method: it's an alias to the specific class instance which the method belongs to. This way every class can identify itself and have access to its members without ambiguity.

Method directives

Class methods can be changed, overloaded, made static and more. A method can have more than one directive. Directives rule the whole polymorphism system in Object Pascal; they can change the call model, too.

virtual, dynamic, override

these three directives are mutually exclusive. virtual means that the method can be overwritten by the derived class. dynamic means the same thing, but the implementation differs: virtual members addresses are stored in a table, while dynamic members do not use tables and do not occupy RAM, but their resolution mechanism is slower.

A derived class can implement its own version of a virtual method, but the base method is still available; if the new method is marked override it hides the base virtual method, which cannot be called anymore. This holds true in case of dynamic methods, too. However you cannot override a method if it's not virtual or dynamic.

static

A static method or variable is common to every instance of the class; one class instance can write a static variable member and every other instance will retain (and read, if accessed) the new value. For this reason, the compiler does NOT pass the 'self' parameter to static methods: it would be nonsense. Moreover, static methods cannot be virtual (but see class methods below).

abstract

A method declared abstract is declared, but not implemented in the base class. Derived classes will be forced to provide their own implementation.

overload

function MultiSum(a, b: integer): integer; overload;
function MultiSum(a, b: AnsiString): AnsiString; overload;

With the overload directive you can declare many methods - functions or procedures - with the same name but different type and parameters.

The class needs the constructor to be implemented in the implementation section of the unit:

implementation

constructor TMyClass.Create;
begin
  inherited;
  SomeVar := 6;
end;

end.

The destructor and all procedures and functions of the class must also be implemented in the implementation section.

Instances of the class can then be declared as variables:

var
  classInstance: TMyClass;

Before using an instance, it must be created with:

begin
  classInstance := TMyClass.Create;
  ...
end;

Classes compared to other structured types

Feature Record Adv Record Object Class
Encapsulation (combining data and methods + hiding visibility) No Yes Yes Yes
Inheritance No No Yes Yes
Class constructor and destructor No Yes Yes Yes
Polymorphism (virtual methods) No No Yes Yes
Memory allocation Stack Stack Stack Heap (Only)
Setting fields to zero on allocation
Managed Types only Managed Types only Managed Types only All fields
Default() function returns a constant with
all fields zeros all fields zeros all fields zeros returns nil
Operator overload (global) Yes Yes Yes Yes
Operator overload (in type only) No Yes No No
Type helpers No Yes No Yes
Virtual constructors, class reference No No No Yes
Variant part (case) as c/c++ union Yes Yes No No
Bitpacked (really packing) Yes Yes No No

Modified from https://forum.lazarus.freepascal.org/index.php/topic,30686.30.html (original author: ASerge).

See also

extended class syntax Examples


navigation bar: data types
simple data types

boolean byte cardinal char currency double dword extended int8 int16 int32 int64 integer longint real shortint single smallint pointer qword word

complex data types

array class object record set string shortstring