A class is a data structure that may contain data members (Constants, Fields and Properties, as well as actions that work with that data (Methods).
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 or 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 the
nested in syntax.
Classes can contain Type Members, including Fields, Properties and even Methods. Also like in classes, the members can be grouped in Visibility Sections.
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 method or property accessor finishes.
Classes can also define Nested Types. Nested types are like regular custom types, except they are considered part of the class and their visibility can be scoped as granular as all class Members.
Nested types are 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 to 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 is automatically 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 Polymorphism topic in the Concepts section, for details.
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 no 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 Polymorphism topic in the Concepts section, for details.
A class can be marked with the
sealed Modifier, to prevent further subclassing.
Extension Classes can add properties, methods, operators and events to an existing type (but not add anything that requires storage, like fields, events or stored properties). These become available to callers if this type is in scope for the caller. The first type in the ancestor defines which type gets extended; optional interfaces can be used to add/implement as interfaces allowing the type to be compatible with that interface.
Read more about Extension Classes here.
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:
abstractForces the class to be abstract; see above.
extensionMakes this an extension class; see above and Extensions.
mappedMakes this a mapped class; see Mapped Types.
partialPartial can be used to spread a type over several files in the same project. All parts must have this modifier then.
readonlyMakes this class readonly. All fields in it will be readonly and can only be set by a constructor and not modified afterwards.
staticStatic classes are classes with only static members. The class modifier is implied on all members.
- Type Members
- Nested Types
- Records in Oxygene
- Value Types vs. Reference Types