Types and OOP Properties

# Attributes and Properties

Klyn distinguishes between stored implementation state and the public surface that exposes it. In practice, properties are the primary way to publish state cleanly, while attributes or backing fields remain an implementation detail.

Backing Fields

    public class Rational:
        private _numerator as Int
        private _denominator as Int

Backing fields usually carry a leading underscore and stay private to the class.

Custom Properties

    public property denominator as Int:
        get:
            return this._denominator
        set:
            if value == 0:
                throw Exception("denominator cannot be 0")
            this._denominator = value

Properties can enforce validation or compute values before they expose data.

Auto-Implemented Properties

    public class Point:
        public property x = 0
        public property y = 0

Auto-properties are ideal when you want a normal property surface but do not need custom getter or setter logic.

Readonly Properties

    public readonly property name as String
    public readonly property offset as Int

Use `readonly` when callers may observe a value but should not mutate it directly.

Property Access Syntax

    r = Rational(1, 3)
    print(r.numerator)
    r.denominator = 5

Properties use ordinary member access syntax. Callers do not need to know whether the property is auto-implemented or backed by custom getter and setter blocks.

When to Use Each Form

Need | Preferred form
--- | ---
Internal implementation state only | Private backing field
Simple public state | Auto-implemented property
Validation or derived logic | Custom property with `get` and/or `set`
Observable but immutable surface | `readonly property`