Skip to content

Classes & OOP

Chuks supports full object-oriented programming with classes, interfaces, inheritance, access modifiers, abstract classes, and more.

class Animal {
public name: string;
public age: int;
constructor(name: string, age: int) {
this.name = name;
this.age = age;
}
public speak(): string {
return this.name + " makes a sound";
}
}
const dog = new Animal("Rex", 5);
println(dog.speak()); // "Rex makes a sound";
class Dog extends Animal {
public breed: string;
constructor(name: string, age: int, breed: string) {
super(name, age);
this.breed = breed;
}
public speak(): string {
return this.name + " barks!";
}
}
const rex = new Dog("Rex", 5, "Labrador");
println(rex.speak()); // "Rex barks!"

Chuks supports inheritance chains of any depth. Each level can call super() for constructors and super.method() for parent methods.

class Base {
var value: int;
constructor(v: int) {
this.value = v;
}
function describe(): string {
return "Base(" + string(this.value) + ")";
}
}
class Middle extends Base {
var label: string;
constructor(v: int, label: string) {
super(v);
this.label = label;
}
override describe(): string {
return "Middle:" + super.describe();
}
}
class Top extends Middle {
constructor(v: int) {
super(v, "top");
}
override describe(): string {
return "Top->" + super.describe();
}
}
var t = new Top(42);
println(t.describe()); // Top->Middle:Base(42)
println(t.label); // top
println(t.value); // 42
ModifierAccess
publicAccessible from anywhere (default)
protectedAccessible from the class and subclasses
privateAccessible only within the class
class Account {
public name: string;
protected balance: float;
private pin: int;
constructor(name: string, balance: float, pin: int) {
this.name = name;
this.balance = balance;
this.pin = pin;
}
}

Properties marked readonly can only be set in the constructor:

class Config {
readonly maxRetries: int;
constructor(retries: int) {
this.maxRetries = retries;
}
}
const cfg = new Config(3)
// cfg.maxRetries = 5 // Error: cannot assign to readonly property
class MathHelper {
static public square(n: int): int {
return n * n;
}
}
println(MathHelper.square(5)); // 25

Abstract classes cannot be instantiated and may contain abstract methods that subclasses must implement:

abstract class Shape {
abstract public area(): float;
public describe(): string {
return "Shape with area: " + this.area();
}
}
class Rectangle extends Shape {
public width: float;
public height: float;
constructor(w: float, h: float) {
this.width = w;
this.height = h;
}
public area(): float {
return this.width * this.height;
}
}

final prevents a class from being extended or a method from being overridden:

final class Singleton {
// Cannot be extended
}
class Base {
final public id(): int {
return 1;
}
}

Use override to explicitly mark methods that override a parent implementation:

class Cat extends Animal {
override public speak(): string {
return this.name + " meows";
}
}

Interfaces define contracts that classes must implement:

interface Printable {
print(): void
}
interface Serializable {
serialize(): string
}
class Document implements Printable, Serializable {
public content: string;
constructor(content: string) {
this.content = content;
}
public print(): void {
println(this.content);
}
public serialize(): string {
return this.content;
}
}

Interface methods can specify nullable return types using T?:

dataType User {
id: int;
name: string;
}
interface UserRepository {
findById(id: int): User?;
getName(id: int): string?;
}

Class methods can be async and return Task<T>. See Concurrency for full details.

class ApiClient {
public async get(url: string): Task<any> {
// perform async work
return { "status": 200 }
}
}
var client = new ApiClient()
var resp: any = await client.get("/users")
enum Color {
Red,
Green,
Blue
}
enum Direction {
North,
South,
East,
West
}
var c: Color = Color.Red;