Class
A class is a stateful type that can be instantiated.
Usage
A trivial class declaration looks like this:
class C() {
/* declarations of class members */
}
Description
Initializer
The class initializer executes when instances of the class are created
(also known as class instantiation).
The parameters to the initializer are specified in parenthesis after the
name of the class in the class declaration.
Extending classes
A class S is declared as a subclass of another class C using the extends
keyword like this:
class S() extends C() {
/* declarations of class members */
}
If a class is declared without using the extends keywords it is a subclass of
IdentifiableObject.
Note that the arguments to the superclasses initializer are
specified in parenthesis after the name of the superclass in the extends
clause.
Satisfying interfaces
A class can satisfy zero or more interfaces using the
satisfies keyword. If the class C is to satisfy interfaces I1 and I2 the
declaration looks like this:
class C() satisfies I1 & I2 {
/* declarations of class members */
}
& is used as the separator between satisfied interfaces because C is
satisfying a type, the
intersection type I1&I2.
Enumerated classes
The subclasses of an abstract class can be constrained to a list of named
classes or toplevel anonymous classes using the of clause.
If the class C is permitted only two direct
subclasses S1 and S2 its declaration would look like this:
abstract class C() of S1 | S2 {
/* declarations of class members */
}
Type parameters
A class declaration lists type parameters with angle brackets (< and >)
after the class name.
class C<Z>() {
/* declarations of class members
type parameter Z treated as a type */
}
A class declaration with type parameters may have a given clause for each declared type parameter
to constraint the permitted type argument.
Parameter list
A class declaration requires a parameter list
Concrete classes
A class that can be instantiated is
concrete. It follows that abstract or formal classes are not concrete.
Abstract classes
A class declaration may be annotated abstract, like this:
abstract class C() {
/* declarations of class members */
}
Abstract classes cannot be instantiated.
Abstract classes may have formal members.
Shared classes
A class declaration may be annotated shared,like this:
shared class C() {
/* declarations of class members */
}
Formal classes
Toplevel classes may not be annotated formal.
Formal classes cannot be instantiated.
A formal class may have formal members.
A block local class may not be annotated formal.
A formal inner class may be subject to
member class refinement.
Default classes
A class may be annotated default if it is contained in a concrete shared
class or interface.
A block local class may not be annotated formal.
A default inner class may be subject to
member class refinement.
Members
The permitted members of classes are classes,
interfaces,
methods,
attributes
and objects.
Aliases
A class alias is a kind of type alias that declares a class in terms of a type expression:
class C() => B();
Member class refinement
An inner class of a class or interface can be subject to member class refinement, which means its instantiation will be polymorphic.
Here's an example where a Reader class declares that concrete
subclasses must (because we used formal) provide an actual Buffer
inner class.
shared abstract class Reader() {
shared formal class Buffer(Character... chars)
satisfies Sequence<Character> {}
// ...
}
shared class FileReader(File file)
extends Reader() {
shared actual class Buffer(Character... chars)
extends Reader::Buffer(chars) {
// ...
}
// ...
}
Within Reader (and elsewhere) we can instantiate the relevant kind of
Buffer with a normal instantiation, Buffer(chars). This allows each
subclass of Reader to implement an appropriate kind of Buffer.
Member class refinement is a lot like the 'abstract factory' pattern in other object-oriented languages, but it's a lot less verbose.
Only formal and default member classes are subject to member class
refinement. A formal member class must be refined by concrete subtypes
of the type declaring the member class—just like a formal method or
attribute. A default member class may be refined—just like
a default method or attribute.
In a subtype of the type declaring the member class the member class
(i.e. in FileReader.Buffer from the example above) must:
- be declared
actual, - have the same name as the member class in the declaring type (
Bufferin the example), - have a parameter list with a compatible signature and,
- extend the member class (you'll need to use
superor::in theextendsclause).
Refined member types are similar to, but not the same as virtual types, which Ceylon does not support.
See also
- Member class refinement in the Ceylon spec