Structs¶
Structs in Kiwi provide a way to bundle data and functionality together.
Defining Structs¶
To define a struct in Kiwi, use the struct keyword followed by the struct name and a block of code defining its properties and methods.
Each concrete struct should define a constructor method, called new.
struct MyStruct
fn new(name)
# Use the `@` symbol to declare an instance variable.
@name = name
end
fn say_hello()
println("Hello, ${@name}!")
end
end
Creating Instances¶
To create an instance of a struct, use the .new() method followed by any arguments the constructor accepts.
Inheritance¶
Kiwi supports single inheritance. Use the < symbol to specify the parent struct.
Method Definition¶
Methods are defined using the fn keyword, followed by the method name and any parameters. Use @ to access the current instance.
Overriding to_string()¶
The override keyword is not required to override to_string().
struct KiwiStruct
fn to_string()
return "I am a Kiwi struct"
end
end
instance = KiwiStruct.new()
string_repr = instance.to_string()
println(instance) # prints: I am a Kiwi struct
println(string_repr) # prints: I am a Kiwi struct
Static Method Definition¶
Methods declared as static can be invoked directly through the struct and cannot be invoked through an instance.
struct MyStruct
static fn static_method()
println("I can be invoked without an instance!")
end
end
MyStruct.static_method() # prints: I can be invoked without an instance!
Static Variables¶
Static variables are shared across all instances of a struct. They belong to the struct itself, not to any individual instance.
Declare a static variable with static @name = value inside the struct body. It is initialized once when the struct is defined.
struct Counter
static @count = 0
fn new()
@@count += 1
end
static fn get(): integer
@@count
end
end
Counter.new()
Counter.new()
Counter.new()
println(Counter.get()) # 3
Inside any method — static or instance — use @@name to read or write a static variable.
struct Logger
static @entries = []
fn new(msg: string)
@@entries = @@entries + [msg]
end
static fn all(): list
@@entries
end
end
Logger.new("started")
Logger.new("finished")
println(Logger.all()) # ["started", "finished"]
Read a static variable from outside the struct with StructName.varname. Write to it with StructName.varname = value.
Access Control¶
Kiwi supports private methods that cannot be called outside the struct definition.
All instance variables are public but readonly. You can explicitly implement accessors and modifiers to control access to them outside of struct scope.
struct MyStruct
fn new(name)
@name = name
end
end
inst = MyStruct.new("kiwi")
println inst.name # kiwi
Type-checking, member queries¶
struct Hashable
fn to_hash()
{}
end
end
struct A < Hashable
fn new(name)
@name = name
end
fn to_hash()
{ name: @name }
end
fn say_hello()
println("Hello, ${@name}!")
end
end
struct B < A
fn say_goodbye()
println("Goodbye, ${@name}!")
foobar()
end
private fn foobar()
println "foobar is private"
end
end
my_obj = B.new("Kiwi")
println my_obj.to_hash() # { "name": "Kiwi" }
# type checking
println my_obj.is_a(Hashable) # true
# set a member
my_obj.set("name", "foobar")
# query members
println my_obj.keys() # ["name"]
println my_obj.values() # ["foobar"]
# clone an object
x = my_obj.clone()
println x # <struct(name=B, identifier=x>
x.say_goodbye() # Goodbye, foobar!\nfoobar is private