Classes
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 class
keyword:
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.
Members
Classes can contain Type Members, including Fields, Properties and even Methods. Also like in classes, the members can be grouped in Visibility Sections.
Invariants
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.
Nested Types
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.
Polymorphism
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 (Object
).
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 Employee
, Manager
, 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 Employee
, Manager
or FamilyMember
.
Please refer to the Polymorphism topic in the Concepts section, for details.
Abstract Classes
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 Car
, Train
and Bike
could provide implementations for the Drive
method.
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.
Sealed Classes
A class can be marked with the sealed
Modifier, to prevent further subclassing.
Extension Classes
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.
Type Visibility
The visibility of a class type can be controlled by applying a Visibility Modifier on the declaration. The default visibility is assembly
.
Other Modifiers
A number of other Type Modifiers can be applied to classes:
abstract
Forces the class to be abstract; see above.extension
Makes this an extension class; see above and Extensions.mapped
Makes this a mapped class; see Mapped Types.partial
Partial can be used to spread a type over several files in the same project. All parts must have this modifier then.readonly
Makes this class readonly. All fields in it will be readonly and can only be set by a constructor and not modified afterwards.static
Static classes are classes with only static members. The class modifier is implied on all members.
See Also
- Type Members
- Polymorphism
- Nested Types
- Records in Oxygene
- Value Types vs. Reference Types