Types and OOP Classes

Classes and Constructors

In Klyn, a class is both a runtime type and the main unit of object-oriented design. This page covers class declarations, constructors, instance and static members, file layout rules, and the basics of working with this.

A Simple Class

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

    public Point(x as Int = 0, y as Int = 0):
        this.x = x
        this.y = y

    public override toString() as String:
        return f"[{this.x}, {this.y}]"

Constructors are named after the class. There is no separate constructor or new keyword.

Creating Objects

p1 = Point()
p2 = Point(10, 20)

p3 = Point(
    1,
    2
)

Constructor calls use ordinary call syntax and may span multiple lines when readability benefits.

Instance Members and this

Use this when you want to emphasize that a property or method belongs to the current instance.

public class Counter:
    public property current as Int = 0

    public tick() as Void:
        this.current++

    public reset() as Void:
        this.current = 0

Instance Storage

Ordinary class instances store one pointer to shared type metadata followed by their instance fields. Primitive fields keep their physical widths: an Int uses four bytes, a Short two, and a Byte one. Automatic properties require backing storage; computed properties and static members do not.

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

assert sizeof(Point) == 16    # 64-bit target: one pointer + two Int fields

sizeof reports the aligned inline instance layout, not the total memory reachable through references, allocator bookkeeping, or shared reflection metadata. It uses the operand's static type and does not evaluate the expression. This also works for abstract classes, native classes, GUI widgets, enums, and concrete generic classes. Native classes include their fixed native state; separately allocated buffers, collection elements, and operating-system resources are not included.

import klyn.collections
import klyn.gui.windows

assert sizeof(Button("Not constructed")) == sizeof(Button)
assert sizeof(MainWindow) > sizeof(Object)
assert sizeof(Int[]) == sizeof(Array<Int>)
assert sizeof(f:[1, 2, 3]) == sizeof(Int[])

callback as (Int) -> Int = lambda(value): value + 1
assert sizeof(callback) == sizeof((Int) -> Int)

Interfaces and function signatures have no single concrete instance layout: sizeof(List<Int>) and sizeof((Int) -> Int) report the reference width, eight bytes on 64-bit platforms. This does not measure the implementing object or a lambda's captured data. Void represents no data, so sizeof(Void) is a compile-time error, as is an operand whose type is unknown. See the String storage model for the distinction between a string object's fixed size and its text payload.

Static Members

public class Settings:
    public static defaultName = "Klyn"

print(Settings.defaultName)

Static members belong to the type, not to a specific instance.

Deep Copy and Receiver Typing

Every object inherits deepCopy() as this. The special return type this means that the static result type follows the static receiver type. At runtime, the copied object keeps its concrete subtype, and nested mutable objects and collections are copied recursively. Cycles and shared references are preserved.

shape as Shape = Circle(10.0)
copy = shape.deepCopy()       # statically Shape, dynamically Circle

assert copy is Shape
assert copy is Circle
assert copy is not shape

Because the static receiver above is Shape, the result cannot be assigned directly to Circle without an explicit checked cast, even though its runtime type is a circle.

File and Public Class Rules

Klyn is strict here
  • A source file may declare at most one public top-level type.
  • The public type must have the same name as its source file.
  • If the file declares a package, the folder path must match that package.
package my.app.core

public class User:
    pass

The example above belongs in my/app/core/User.kn.

Method Syntax Is Different from Function Syntax

Inside a class body, methods are declared directly with modifiers such as public, private, or static. They do not use the def keyword.