Traits
A trait is a reusable set of fields and methods that a class can adopt. Traits let you share behavior across classes without forcing them into the same inheritance chain.
trait Damageable {
Health = 100
function TakeDamage(amount) {
this.Health -= amount
}
function IsAlive() {
return this.Health > 0
}
}
class Enemy with Damageable {
}
local enemy = new Enemy()
enemy.TakeDamage(25)
print(enemy.Health)
print(enemy.IsAlive())
Keyword: with
For a class to use a trait, it uses the with keyword.
trait A {
}
class Base {
}
class Implementation : Base with A {
}
Required methods
A trait can provide an implementation for a function that can be overriden, yet if the function does not contain a body, then a class is required to implement the function.
trait Damageable {
Health = 100
// TakeDamage doesn't have a body, thus it's required to be implemented by a class
function TakeDamage(amount)
}
class Enemy with Damageable {
// If Enemy does not have this function, then a error will appear
function TakeDamage(amount) {
this.Health -= amount
}
}
Multiple traits
It’s possible for a class to adopt multiple traits.
trait Named {
Name = "Unknown"
function PrintName() {
print(this.Name)
}
}
trait Damageable {
Health = 100
function TakeDamage(amount) {
this.Health -= amount
}
}
class Enemy with Named, Damageable {
}
local enemy = new Enemy()
enemy.Name = "Goblin"
enemy.PrintName()
enemy.TakeDamage(10)
print(enemy.Health)
Trait Inheritance
A trait can inherit another trait
trait Named {
Name = "Unknown"
function GetName() {
return this.Name
}
}
trait LoudNamed : Named {
function PrintName() {
print(this.GetName())
}
}
class Enemy with LoudNamed {
}
Class override
If the class defines a method/field, then the class will override what is defined in the trait.
trait Greeter {
function Greet() {
print("Hello from trait")
}
}
class NPC with Greeter {
function Greet() {
print("Hello from class")
}
}
local npc = new NPC()
npc.Greet() // Hello from class