Skip to content

Classes and Objects

ktox-lua provides full support for Kotlin classes, including primary and secondary constructors, properties with custom accessors, methods, and single inheritance. Classes are transpiled into Lua tables using metatables to simulate class-like behavior and inheritance.

Class Definition and Constructors

A standard Kotlin class is transpiled into a Lua table that acts as a prototype, with a :new() method for instantiation.

Kotlin:

open class Animal(val name: String) {
    var age: Int = 0

    fun describe(): String = "Animal: ${this.name}, Age: ${this.age}"
}

Lua:

Animal = {}
Animal.__index = Animal

function Animal:new(name)
    local self = setmetatable({}, Animal)
    self.name = name
    self.age = 0
    return self
end

function Animal:describe()
    return "Animal: " .. tostring(self.name) .. ", Age: " .. tostring(self.age)
end

-- init blocks and property initializers are transpiled into the constructor
function Animal:new(name)
    local self = setmetatable({}, Animal)
    self.name = name
    self.age = 0
    -- Body of init blocks:
    print("New animal: " .. tostring(name))
    return self
end

Inheritance

Inheritance is implemented by setting the metatable of the child class prototype to the parent class prototype.

Kotlin:

class Dog(name: String, val breed: String) : Animal(name) {
    fun bark(): String = "${this.name} (${this.breed}) says: Woof!"
}

Lua:

Dog = setmetatable({}, {__index = Animal})
Dog.__index = Dog

function Dog:new(name, breed)
    local self = Animal:new(name) -- Call parent constructor
    setmetatable(self, Dog)       -- Re-set metatable to child class
    self.breed = breed
    return self
end

function Dog:bark()
    return tostring(self.name) .. " (" .. tostring(self.breed) .. ") says: Woof!"
end

Properties and Accessors

Kotlin properties with custom getters or setters are transpiled into methods. Note that simple properties are transpiled as direct table field access in Lua for performance.

Kotlin:

class Rectangle(var width: Int, var height: Int) {
    val area: Int
        get() = width * height
}

Lua:

Rectangle = {}
Rectangle.__index = Rectangle

function Rectangle:new(width, height)
    local self = setmetatable({}, Rectangle)
    self.width = width
    self.height = height
    return self
end

-- Custom getter becomes a method
function Rectangle:getArea()
    return self.width * self.height
end

Data Classes

Data classes include automatically generated methods like equals, toString, copy, and componentN.

Kotlin:

data class AppException(val message: String)

Lua:

AppException = {}
AppException.__index = AppException

function AppException:new(message)
    local self = setmetatable({}, AppException)
    self.message = message
    return self
end

function AppException:equals(other)
    return self.message == other.message
end
AppException.__eq = function(a, b) return a:equals(b) end

function AppException:toString()
    return "AppException(" .. "message=" .. tostring(self.message) .. ")"
end
AppException.__tostring = function(a) return a:toString() end

function AppException:copy(message)
    if message == nil then message = self.message end
    return AppException:new(message)
end

function AppException:component1()
    return self.message
end

Objects and Companion Objects

Kotlin object declarations and companion objects are transpiled to single Lua tables.

Kotlin:

object Database {
    fun connect() = "Connected"
}

class User {
    companion object {
        fun create() = User()
    }
}

Lua:

Database = {}
function Database:connect()
    return "Connected"
end

User = {}
User.__index = User
-- ... (User:new implementation)

User.Companion = {}
function User.Companion:create()
    return User:new()
end

Data Classes

Kotlin data classes provide automatically generated equals, toString, copy, and componentN methods in Lua.

Kotlin:

data class User(val name: String, val age: Int)

Lua:

function User:toString()
    return "User(name=" .. tostring(self.name) .. ", age=" .. tostring(self.age) .. ")"
end

function User:copy(name, age)
    return User:new(name or self.name, age or self.age)
end

function User:equals(other)
    if self == other then return true end
    if not ktox_isinstance(other, User) then return false end
    return self.name == other.name and self.age == other.age
end

Enum Classes

enum class is transpiled to a table containing each entry. Each entry is represented by a table (or its value if it has a constructor).

Kotlin:

enum class Direction { NORTH, SOUTH }

Lua:

Direction = {
    NORTH = "NORTH",
    SOUTH = "SOUTH"
}

Interfaces

Kotlin interfaces are transpiled to a table with empty function stubs to ensure compatibility.

Kotlin:

interface Drawable {
    fun draw()
}

Lua:

Drawable = {}
function Drawable:draw() end

Instantiation and Method Calls

In Lua, you must use the colon : operator when calling methods or the constructor to ensure self is correctly passed.

Kotlin:

val dog = Dog("Rex", "Labrador")
val sound = dog.bark()

Lua:

local dog = Dog:new("Rex", "Labrador")
local sound = dog:bark()