Note: information on this page refers to Ceylon 1.0, not to the current release.

Values and attributes

There are two kind of value:

  • A reference holds state, that is, a reference to another object.
  • A value defined as a getter (with, optionally, a matching setter) does not directly hold state, instead it defines how a "derived" value is computed.

When a value is a member of a type, is it called an attribute.

Usage

A variable reference:

variable String firstName = "John";
variable String lastName = "Smith";

A value getter:

// A getter with a fat arrow
shared String name => firstName + " " + lastName;

// A getter with a block
shared String name {
    return firstName + " " + lastName;
}

A value setter:

assign name {
    assert (is [String, String] parts
            = parseName(name));
    firstName = parts[0];
    lastName = parts[1];
}

Description

References

References are just holders of state. A reference attribute declared within a class body represents state associated with an instance of the class. A local reference (that is, a reference declared within a block) represents state associated with execution of that block.

variable values

If a reference is annotated variable, it can be assigned more than once. Otherwise it must be specified exactly once. Moreover the specification must occur before its first use.

Getters

A getter defines a derived value that is computed when needed.

From the point of view of the code evaluating a value, it is impossible to determine whether the value is implemented as a reference or as a getter. It's even possible to refine a reference with a getter, or vice versa.

Like functions, you can either use a block of statements or the fat arrow (=>) syntax if the value can be computed from a single expression.

Setters

A setter defines what to do when a derived variable value is assigned.

From the point of view of the code assigning a value, it is impossible to determine whether the value is implemented as a reference or as a setter. It's even possible to refine a variable reference with a getter/setter pair, or vice versa.

Every setter must have a corresponding getter with the same name.

The getter declaration must occur earlier in the body containing the setter declaration.

Attribute receiver

Attribute evaluations have a 'receiver', an instance of the type that declares the method. Within the getter or setter body, the expression this refers to this receiving instance.

A top level value does not have a receiver.

Type inference

Local value declarations often don't need to explictly declare a type, but can instead use type inference via the value keyword.

void f() {
    value string = ""; //inferred type String
}

late values

A value can be declared late in which case the typechecker's definite specification checks are not performed.

formal and default attributes

An attribute declaration may be annotated formal or default. A formal or default attribute must also be annotated shared.

A formal attribute does not specify an implementation. A formal attribute must be refined by concrete classes which inherit the containing class or interface.

A default attribute may be refined by types which inherit the containing class or interface.

shared values

A toplevel value declaration, or a value declaration nested inside the body of a containing class or interface, may be annotated shared.

  • A toplevel shared value is visible wherever the package that contains it is visible.
  • A shared value nested inside a class or interface is visible wherever the containing class or interface is visible.

Metamodel

Value declarations can be manipulated at runtime via their representation as ValueDeclaration instances. An applied function (i.e. with all type parameters specified) corresponds to either a Value or Attribute model instance.

See also