Classes take part in a hierarchy of types and can descend from each other to form that hierarchy (more on that below). An instance of a class is commonly referred to as an "object".
A class type is declared using the
class keyword, followed by zero or more member declarations, and closed off with the
end keyword. Optionally, a base class and/or a list of one of more interfaces implemented by the class can be provided in parenthesis behind the
type MyClass = public class(Object, IMyInterface) private fName: String; fValue: Integer; public property Name: String read fName; property Value: Integer read fValue; end;
Like all custom types, classes can be nested in other types with
nested in syntax.
Classes can define Invariants to help ensure a consistent state. Invariants are boolean expressions that will automatically be enforced by the compiler every time a methor or property accessor finishes.
Nested types aree declared using the
nested in syntax, and (outside of the containing class) are referred to in the same way as static class members would – prefixed with the name of the class, and dot.
Refer to the Nested Types topic for more details.
As hinted above, classes are part of a class hierarchy, where each class except the root) has an ancestor class that it descends from and extends. You can think of this hierarchy as a tree, with a common root (
Classes can be treated polymorphically. That means an object (a concrete instance of a class) can be treated the same as any any of its base classes. This allows code or be written that can work with a base class (or even
Object itself), and it can be applied to any descendant of the same class, as well.
Individual members of a class can be virtual, which means that descendant classes can override their implementation to provide more specific behavior. When code working with a common base class accesses virtual members, at runtime execution automatically is passed to the implementation for the concrete instance.
For example code could be written for a list of
Person classes, which, at runtime, includes various concrete subclasses or persons, such as
FamilyMember or the like. The code has access to all (visible) members declared on
Person, but might end up transparently calling more specific implementations of these members provided by
Please refer to the Concepts section, for details.topic in the
A class can be marked with the
abstract Modifier, to indicate that it is an abstract base class. Abstract classes cannot be instantiated, and they may (but don't have to) contain abstract Members – that is, members that have been defined on the class, but not implemented.
Descendants from an abstract classes class can become non-abstract, if they provide overriden implementations for all abstract members.
Consider a class hierarchy of vehicles, where the base class
Vehicle can represent any kind of vehicle, but not a concrete type. It might provide an abstract
Drive method, but o implementation (since there is no one way to drive "any vehicle"). It makes no sense to create an instance of a
Vehicle. Concrete subclasses such as
Bike could provide implementations for the
Yet, even though
Vehicle is abstract, code can be written that knows how to call
Drive on *any& vehicle.
Again. please refer to the Concepts section, for details.topic in the
A class can be marked with the
sealed Modifier, to prevent further subclassing.
The visibility of a class type can be controlled by applying a Visibility Modifier on the declaration. The default visibility is
A number of other Type Modifiers can be applied to classes: