Skip to content

Member Accesses

A member access is used to refer to members of a complex data structure such as

The general syntax of a member access is this:

<receiver>.<member>

Here, the receiver is some expression (the legal choices are explained below), while the member is always a reference.

Member Access of Class Members

To understand how we can access members of a class we must first look briefly at a declaration of the class we use in the following examples:

class DecisionTree() {
    static attr verboseTraining: Boolean

    attr maxDepth: Int
}

This class has a static attribute called verboseTraining, which has type Boolean. Static means that the attribute is shared between all instances of the class and can be accessed on the class itself, rather than a specific instance.

Moreover, the class has an instance attributemaxDepth, which is an integer. This must be accessed on a specific instance of the class.

Member Access of Static Class Member

Let us look at how to access the static attribute verboseTraining to retrieve its value:

DecisionTree.verboseTraining

These are the syntactic elements of this member access:

  • The receiver, which is the name of the class (here DecisionTree)
  • A dot.
  • The name of the static member of the class (here verboseTraining)

Note that we cannot access a static member from an instance of the class. We must use the class itself.

Member Access of Instance Class Member

Contrary to static member accesses, we can only access instance members on an instance of a class:

DecisionTree().maxDepth

We now take apart the syntax again:

  • The receiver, here a call of the constructor of the class DecisionTree. This creates an instance of this class.
  • A dot.
  • The name of the instance member (here maxDepth).

Note that instance members cannot be accessed from the class itself, but only from its instances.

Member Access of Enum Variants

A member access can also be used to access the variants of an enum. Here is the declaration of the enum that we use in the example:

enum SvmKernel {
    Linear,
    RBF
}

This enum is called SvmKernel and has the two variants Linear and RBF.

We can access the variant Linear using this member access:

SvmKernel.Linear

These are the elements of the syntax:

  • The receiver, which is the name of the enum (here SvmKernel).
  • A dot.
  • The name of the variant (here Linear).

This syntax is identical to the member access of static class members.

Member Access of Results

If the result record that is produced by a call has multiple results, we can use a member access to select a single one. Here is the global function we use to explain this concept:

fun divideWithRemainder(dividend: Int, divisor: Int) -> (quotient: Int, remainder: Int)

The global function divideWithRemainder has two parameters, namely dividend and divisor, both of which have type Int. It produces two results, quotient and remainder, which also have type Int.

If we are only interested in the remainder of 12 divided by 5, we can use a member access:

divideWithRemainder(12, 5).remainder

Here are the syntactic elements:

  • The receiver, which is a call.
  • A dot.
  • The name of the result (here remainder).

While it is also possible to access the result by name if the result record contains only a single entry, there is no need to do so, since this result can be used directly. If you still use a member access and the singular result of the call has the same name as an instance member of the corresponding class, the instance member wins.

To explain this concept further, we need the following declarations:

class ValueWrapper {
    attr value: Int
}

fun createValueWrapper() -> value: ValueWrapper

We first declare a class called ValueWrapper, which has an attribute value of type Int. Next, we declare a function, which is supposed to create an instance of the class ValueWrapper and put it into the result value.

Let us now look at this member access:

createValueWrapper().value

This evaluates to the attribute, i.e. an integer, rather than the result, which would be an instance of ValueWrapper.

If you want the result instead, simply omit the member access:

createValueWrapper()

Null-Safe Member Accesses

If an expression can be null, it cannot be used as the receiver of a regular member access, since null does not have members. Instead, a null-safe member access must be used. A null-safe member access evaluates to null if its receiver is null. Otherwise, it evaluates to the accessed member, just like a normal member access.

The syntax is identical to a normal member access except that we replace the dot with the operator ?.:

nullableExpression?.member