Search code examples
propertiesceylon

Properties (getters and setters) in Ceylon


How do I define a property in Ceylon? I know I can write getName and setName functions to get and set a backing variable:

class Circle(shared variable Float radius) {
    shared Float getArea() {
        return pi * radius ^ 2;
    }

    shared void setArea(Float area) {
        radius = sqrt(area / pi);
    }
}

value circle = Circle(4.0);
circle.setArea(10.0);
print(circle.getArea());

But I would like to be able to provide attribute-like access to the property:

value circle = Circle(4.0);
circle.area = 10.0;
print(circle.area);

How do I do this in Ceylon?


Solution

  • Getters are declared like defining a function with no parameter list. The getter body then behaves like a normal function and must return the calculated value of the property.

    variable String local_var = "Hello world!";
    
    // Getter
    String name1 {
        return local_var;
    }
    
    // Also getter, using functional syntax for body
    String name2 => local_var;
    

    Setters are declared using the assign keyword. The setter body then behaves like a void function, performing whatever mutation of the local environment is appropriate and must not return a value. The incoming value being assigned can be referred to in the body via the name of the property.

    // Setter
    assign name1 {
        local_var = name1; // name1 here is value being assigned
    }
    
    // Also setter, using modified functional syntax
    assign name2 => local_var = name2;
    

    Unlike most programming languages, properties can be top level members of the package, not just members of a class:

    class Circle(shared variable Float radius) {
        // Class-level getter
        shared Float area {
            return pi * radius ^ 2;
        }
    
        // Class-level setter
        assign area {
            radius = sqrt(area / pi);
        }
    }
    
    Circle window = Circle(1.0);
    
    // Top-level getter
    Circle outer_window => Circle(window.radius * 2);
    
    // Top-level setter
    assign outer_window => window.radius = outer_window.radius / 2;