Qore Programming Language Reference Manual
0.8.11.1
|
Classes define types of Qore objects. Classes can define members and methods, which are attributes of the class and functions that operate only on the objects of that class, respectively. Furthermore access to class members and methods can be restricted with the private
keyword, and classes can be subclassed to support polymorphism.
[public] [final] class [
namespace_path::...]
class_identifier] [inherits [private|public] [
namespace_path::...]
parent_class_identifier[, ...]] {
[[private] $.
member_name[, ...];]
[private|public {
[[
member_type] $.
member_name [=
initialization_expression];]
[static [
static_member_type]
static_member_name [=
initialization_expression];]
[const
constant_name =
initialization_expression;]
}]
[[final] [private|public] [deprecated] constructor([
[param_type] $
param_name [=
default_initialization_expression], ...]) [:
parent_class_name(
args...), ...] {
}]
[[static|final] [synchronized] [private|public] [deprecated]
method_name([
[param_type] $
param_name [=
default_initialization_expression], ...]) {
}]
[[abstract] [private|public]
method_name([
[param_type] $
param_name [=
default_initialization_expression], ...]);
...
}
When defining a user module, class declarations can be preceded by public, which means that the class will be available (imported) in the Program object importing the module. When a class is declared public outside of a user module, it means that the class can be inherited in any child Program objects created in the same scope. See public for more information. Note that classes can also be imported singly by using the Program::importClass() method.
";"
) is required to terminate a class declaration (in fact using a semicolon would raise a parse exception).[public] class [
namespace_path::...]
class_identifier [inherits [private|public] [
namespace_path::...]
parent_class_identifier[, ...]];
[[private|public] [deprecated] [
namespace_path::...]
class_identifier::constructor([
[param_type] $
param_name [=
default_initialization_expression], ...]) [:
parent_class_name(
args...), ...] {
}]
[[static|final] [synchronized] [private|public] [deprecated] [
namespace_path::...]
class_identifier::
method_name([
[param_type] $
param_name [=
default_initialization_expression], ...]) {
}]
[abstract [private|public] [
namespace_path::...]
class_identifier::
method_name([
[param_type] $
param_name [=
default_initialization_expression], ...]);
"$"
or "$."
prefixes can be used with variable or method or member names as in the specifications above. Class members, class constants, and static class variables can only be declared in an in-line class definition (the first example above). If a class has at least one public member declared (or inherits a class with at least one public member declared), then only those members declared as public can be accessed from outside the class, and from within the class only members explicitly declared can be accessed as well (unless the class also defines a memberGate() method). In this way typographical errors in member names can be caught (at parse time if types are declared)."-x"
or "--exec-class"
command-line arguments to tell Qore to instantiate the class instead of doing normal top-level execution (in fact, the "--exec-class"
argument disallows the use of top-level statements entirely). For more information, please see qore Executable Command-Line Processing and Parse Directives.final
cannot be subclassed, and, by extension, no methods of a final
class can be reimplemented as well.final
classes.public
keyword as well. Public methods have no class protection and can be called from any code context.private
keyword can only be called by other member functions of the same class or of derived classes. Any attempt to call these methods from outside the class hierarchy will result in a run-time exception.synchronized
keyword will only run in one thread at a time.static
keyword are like regular functions that are attached to the class. These methods are not associated with a particular object's state and therefore are not allowed to refer to object members or call non-static methods. Also, no reference to the special $self
variable is allowed within static methods.private
or public
or synchronized
like non-static methods; static methods can also access private members of a class (through an object of the class for non-static members).abstract
keyword define methods interfaces that must be defined in child classes for the class to be instantiated. Methods defining the declared interfaces in child classes must define exactly the same paramters in order for the abstract method to match, but the return type of the concrete method in the child class has to simply be compatible with the return type of the abstract method in the parent class.";"
).abstract
keyword can only be used in abstract method declaration; the use of this keyword with a method declaration with a method body will cause a parse exception to be thrown.Name | Description |
constructor( [params...]) {} | Called when objects are created when instantiated by a variable declaration with a class type and constructor arguments or explicitly with the new operator. User code may not explicitly call constructor() methods directly. In a class tree, constructor() methods are called for base classes first in left-to-right, depth-first declaration order.constructor() methods may be overloaded and also private constructors may be defined. Private constructors can only be called from within the class. |
copy() {} | When a user explicitly calls a copy method, Qore will generate a new object with references to the same members as the source object. Then, if there are any base classes, base class copy() methods are called in the same order as the constructor() methods. If a copy() method is defined, it will be run in the new object with a reference to the old object passed as the first argument. Any other arguments passed to the copy() method are ignored.copy() methods cannot be overloaded and cannot be private. |
destructor() {} | Called when objects go out of scope or are explicitly deleted. User code may not explicitly call destructor() methods. In a class tree, destructor() methods are called for base classes in the opposite order in which the constructors are called.destructor() methods cannot be overloaded and cannot be private. |
any memberGate( string $ member_param_name) {} | If this method is implemented in the class, it is called when read access is attempted to private member or members that do not exist in the current object; the return value of this method is returned as the value of the member.memberGate() methods cannot be overloaded and are not inherited by subclasses. |
any methodGate( string $ method_param_name, ...) {} | If this method is implemented in the class, it is called when methods are called on the object that do not exist in the current object and the return value of this method is returned as the value of the method call.methodGate() methods cannot be overloaded and are not inherited by subclasses. |
memberNotification( string $ member_param_name) {} | If this method is implemented in the class, it is called when an object member is updated outside the class with the member name as the argument. Note that this method is called after the member has been updated and without locking; the call is not atomic respective to other threads that also may update the same member simultaneously.memberNotification() methods cannot be overloaded and are not inherited by subclasses. |
final
cannot be reimplemented in a subclass. Methods can be declared final
to prevent a subclass from altering the behavior of a method that is critical to the class's functionality.final
:final
final
final
final
methods.private
or public
. The following is an example of a class constant definition:private
or public
. The following is an example of a static class variable definition:pivate
can only be accessed within the class hierarchy; trying to access private members form outside the class hierarchy will result in either a parse or runtime exception, depending on when the illegal acceess is caught.$.
member_name$self
is instantiated in every non-static method, representing the current object (similar to this
in C++ or Java). Therefore if you need to access hash members which are not valid Qore identifiers, then enclose the member name in double quotes after the dot operator as follows:memberGate()
method, then whenever a non-existent member of the class is accessed (read), this method will be called with the name of the member as the sole argument, so that the class can create the member (or react in some other way) on demand. This method is also called when methods of the same class try to access (read) non-existent methods, but is not called from within the memberGate()
method itself.memberNotification()
method, which is called whenever an object member is modified from outside class member code. In this case, the memberNotification()
method is called with the name of the member that was updated so that an object can automatically react to changes to its members (writes to members) from outside the class. This method is not called when members are updated from within class member code.$argv
local variable is instantiated as usual in all class methods where there are more arguments than variables declared in the method declaration.[[
namespace_path::...]
parent_class_name::]$.
method_name([
args, ...])
"$."
prefix as in the following example:METHOD-IS-PRIVATE
(if the method is private) or BASE-CLASS-IS-PRIVATE
(if the method resolves to a privately-inherited base class) exception is raised.methodGate()
method, then whenever a non-existent method of the class is called, the methodGate() method will be called with the name of the member as the first argument (prepended to the other arguments to the non-existant method), so that the class simulate or redirect the method call. This method is also called when methods of the same class try to call non-existent methods, but is not called from within the methodGate()
method itself.Class inheritance is a powerful concept for easily extending and resuing object-oriented code, but is also subject to some limitations. This section explains how class inheritance works in Qore.
Classes inherit the methods of a parent class by using the inherits
keyword as specified above. Multiple inheritance is supported; a single Qore class can inherit one or more classes. When a class is inherited by another class, it is called a base class or parent class. Private inheritance is specified by including the keyword private
before the inherited class's name. When a class is privately inherited, it means that the inherited class's public declarations (members, constants, methods, etc) are treated as private in the context of accesses outside the class.
Inheritance is public
by default, to inherit a class privately, use the private
keyword before the class name or class path to inherit as follows:
It is not legal to directly inherit the same class directly more than once; that is; it is not legal to list the same class more than once after the inherits
keyword. However, it is possible that a base class could appear more than once in the inheritance tree if that class is inherited separately by two or more classes in the tree.
In this case, the base class will actually only be inherited once in the subclass, even though it appears in the inheritance tree more than once. This must be taken into consideration when designing class hierarchies, particularly if base class constructor parameters for that class are explicitly provided in a different way by the inheriting classes.
Subclasses can give explicit arguments to their base class constructors using a special syntax (only available to subclass constructors) similar to the C++ syntax for the same purpose as follows:
[[private|public] [deprecated] constructor([
[param_type] $
param_name [=
default_initialization_expression], ...]) [:
parent_class_name(
args...), ...] {
}]
Here is a concrete example of giving arguments to an inherited base class:
Because base class constructors are executed before subclass constructors, the only local variables in the constructor that can be referenced are those declared in the subclass constructor declaration (if any). What this means is that if you declare local variables in the expressions giving base class arguments, these local variables are not accessible from the constructor body.
Classes inherited using the private
keyword encapsulate the functionality (members, constants, methods, etc) of the parent class privately in the child class; that is, any access to the privately-inherited parent class's functionality from outside the class will result in either a parse-time or runtime exception, depending on when the error is caught.
Classes are inherited publically by default; public inheritance means that the parent class's functionality (members, constants, methods, etc) have the same visibility in the child class as they do in the parent class. For example, a public method in the parent class will also be public in the child class if the parent class is inherited publically. Respectively, private methods of publically-inherited parent classes will still be private in child classes.