Full OOP with fields and methods. Every user-defined class implicitly extends Object, inheriting getType(), toString(), and isInstanceOf().
Class:Create(Animal) {
Var:String name;
Var:Number age;
function setName(String n) {
name = n;
}
function speak() {
Konsol:Print(name + " says hello");
}
function getAge() : Number {
return age;
}
}
Fields are declared with Var:Type fieldName; inside the body. Methods are declared with function. Inside a method, fields are accessible directly by name.
Class:Animal dog; // single instance via Class:TypeName
Var:Animal cat; // equivalent shorthand: Var:TypeName
dog.name = "Rex";
dog.age = 3;
dog.setName("Buddy");
dog.speak();
Var:Number a = dog.age;
Field access for reading uses instance.field. For writing, assign directly: instance.field = value.
Method calls use instance.method(args). Modified fields are written back to the instance after each method call.
A class can extend another class with extends:
Class:Create(Dog extends Animal) {
function speak() {
Konsol:Print(name + " barks");
}
}
The subclass inherits all fields and methods of the parent. Overriding a method replaces the parent's implementation for that subclass.
List:Animal pack; // list of Animal instances
Array:New herd[10]:Animal; // array of Animal instances
Each Class:TypeName varName (or Var:TypeName varName) creates an independent instance with its own copy of the fields.
// 07_classes.ks — Class:Create (fields + methods)
Konsol:Print("=== Classes ===");
// ── Counter class ─────────────────────────────────────────────────────────────
Class:Create(Counter) {
Var:Number value;
function reset() {
value = 0;
}
function increment() {
value = value + 1;
}
function decrement() {
value = value - 1;
}
function add(Number n) {
value = value + n;
}
function get() : Number {
return value;
}
}
Class:Counter c;
c.increment();
c.increment();
c.increment();
Konsol:Print("after 3 increments: ${c.value}");
c.decrement();
Konsol:Print("after decrement: ${c.value}");
c.add(10);
Konsol:Print("after add(10): ${c.value}");
c.reset();
Konsol:Print("after reset: ${c.value}");
// ── Animal class ──────────────────────────────────────────────────────────────
Class:Create(Animal) {
Var:String name;
Var:String species;
Var:Number age;
function setName(String n) {
name = n;
}
function birthday() {
age = age + 1;
}
function describe() {
Konsol:Print("${name} is a ${species} aged ${age}");
}
}
Class:Animal dog;
dog.name = "Rex";
dog.species = "dog";
dog.age = 2;
dog.describe();
dog.birthday();
dog.describe();
dog.setName("Buddy");
dog.describe();
// Two independent instances
Class:Animal cat;
cat.name = "Whiskers";
cat.species = "cat";
cat.age = 5;
cat.describe();
// ── Stack class ───────────────────────────────────────────────────────────────
/* Simulated stack using a fixed array field + a top index.
MINKS classes don't support embedded arrays, so we use
numbered fields as slots (max 4 items for this demo). */
Class:Create(Stack4) {
Var:Number s0;
Var:Number s1;
Var:Number s2;
Var:Number s3;
Var:Number top;
function push(Number v) {
if (top == 0) { s0 = v; }
if (top == 1) { s1 = v; }
if (top == 2) { s2 = v; }
if (top == 3) { s3 = v; }
top = top + 1;
}
function peek() : Number {
if (top == 1) { return s0; }
if (top == 2) { return s1; }
if (top == 3) { return s2; }
if (top == 4) { return s3; }
return 0;
}
function size() : Number {
return top;
}
}
Konsol:Print("--- Stack4 ---");
Class:Stack4 stk;
stk.push(10);
stk.push(20);
stk.push(30);
Konsol:Print("size = ${stk.size()}");
Konsol:Print("peek = ${stk.peek()}");
// 14_inherit_basic.ks — Single-level inheritance: child gets parent fields + methods
Konsol:Print("=== Basic Inheritance ===");
// ── Base class ────────────────────────────────────────────────────────────────
Class:Create(Shape) {
Var:String color;
Var:String label;
function setColor(String c) {
color = c;
}
function describe() {
Konsol:Print("${label} | color: ${color}");
}
}
// ── Circle extends Shape ──────────────────────────────────────────────────────
// Inherits: color, label, setColor(), describe()
// Adds: radius, area()
Class:Create(Circle extends Shape) {
Var:Number radius;
function setRadius(Number r) {
radius = r;
}
function area() : Number {
// pi * r^2 (using ^ for power)
return 3.14159 * radius ^ 2;
}
function describe() {
// Override: include radius in output
Konsol:Print("Circle | color: ${color} | radius: ${radius}");
}
}
// ── Rectangle extends Shape ───────────────────────────────────────────────────
// Inherits: color, label, setColor(), describe()
// Adds: width, height, area()
Class:Create(Rectangle extends Shape) {
Var:Number width;
Var:Number height;
function setSize(Number w, Number h) {
width = w;
height = h;
}
function area() : Number {
return width * height;
}
function describe() {
Konsol:Print("Rect | color: ${color} | size: ${width} x ${height}");
}
}
// ── Usage ─────────────────────────────────────────────────────────────────────
Class:Circle c;
c.setColor("red");
c.label = "my circle";
c.setRadius(5);
c.describe();
Var:Number _ret = 0;
Math:Round(c.area(), _ret);
Konsol:Print(" area = ${_ret}");
Class:Rectangle r;
r.setColor("blue");
r.label = "my rect";
r.setSize(4, 6);
r.describe();
Konsol:Print(" area = ${r.area()}");
// Inherited describe() on a plain Shape
Class:Shape s;
s.color = "green";
s.label = "plain shape";
s.describe();
// Two circles are independent
Class:Circle c2;
c2.setColor("yellow");
c2.setRadius(3);
c2.describe();
Konsol:Print(" area = ${c2.area()}");
// 15_inherit_override.ks — Method override: child replaces a parent method
Konsol:Print("=== Method Override ===");
// ── Base ──────────────────────────────────────────────────────────────────────
Class:Create(Animal) {
Var:String name;
Var:Number legs;
function setName(String n) {
name = n;
}
function speak() {
Konsol:Print("${name} makes a generic sound");
}
function info() {
Konsol:Print("${name} has ${legs} legs");
}
}
// ── Dog: overrides speak(), inherits info() ────────────────────────────────────
Class:Create(Dog extends Animal) {
Var:String breed;
function speak() {
Konsol:Print("${name} says: Woof!");
}
function fetch() {
Konsol:Print("${name} fetches the ball");
}
}
// ── Cat: overrides speak(), inherits info() ────────────────────────────────────
Class:Create(Cat extends Animal) {
Var:Boolean indoor;
function speak() {
Konsol:Print("${name} says: Meow!");
}
function purr() {
Konsol:Print("${name} purrs...");
}
}
// ── Bird: overrides speak() and info() ───────────────────────────────────────
Class:Create(Bird extends Animal) {
Var:Number wingspan;
function speak() {
Konsol:Print("${name} says: Tweet!");
}
function info() {
// Override info to include wingspan
Konsol:Print("${name} has ${legs} legs and wingspan ${wingspan}");
}
}
// ── Demo ──────────────────────────────────────────────────────────────────────
Class:Animal base;
base.name = "GenericAnimal";
base.legs = 4;
base.speak();
base.info();
Konsol:Print("---");
Class:Dog d;
d.name = "Rex";
d.legs = 4;
d.breed = "Labrador";
d.speak(); // overridden — "Woof!"
d.info(); // inherited from Animal
d.fetch(); // Dog-only
Konsol:Print("---");
Class:Cat c;
c.name = "Whiskers";
c.legs = 4;
c.indoor = true;
c.speak(); // overridden — "Meow!"
c.info(); // inherited
c.purr(); // Cat-only
Konsol:Print("---");
Class:Bird b;
b.name = "Tweety";
b.legs = 2;
b.wingspan = 30;
b.speak(); // overridden — "Tweet!"
b.info(); // overridden — shows wingspan too
// 16_inherit_chain.ks — Multi-level inheritance chain
Konsol:Print("=== Inheritance Chain ===");
// Level 1 ─────────────────────────────────────────────────────────────────────
Class:Create(LivingThing) {
Var:Boolean alive;
Var:Number energy;
function init() {
alive = true;
energy = 100;
}
function breathe() {
Konsol:Print("breathes");
}
function status() {
Konsol:Print("alive: ${alive} | energy: ${energy}");
}
}
// Level 2: Animal extends LivingThing ─────────────────────────────────────────
// Inherits: alive, energy, init(), breathe(), status()
// Adds: name, move()
Class:Create(Animal extends LivingThing) {
Var:String name;
function setName(String n) {
name = n;
}
function move() {
energy = energy - 10;
Konsol:Print("${name} moves (energy now ${energy} )");
}
function status() {
// Override to include name
Konsol:Print("${name} | alive: ${alive} | energy: ${energy}");
}
}
// Level 3: Dog extends Animal ─────────────────────────────────────────────────
// Inherits: alive, energy, init(), breathe(), setName(), move(), status()
// Adds: breed, fetch()
Class:Create(Dog extends Animal) {
Var:String breed;
function setBreed(String b) {
breed = b;
}
function fetch() {
energy = energy - 20;
Konsol:Print("${name} the ${breed} fetches! (energy now ${energy} )");
}
function status() {
// Override again at this level
Konsol:Print("${name} ( ${breed} ) | alive: ${alive} | energy: ${energy}");
}
}
// Level 4: GuideDog extends Dog ───────────────────────────────────────────────
// Inherits everything from Dog (and transitively Animal, LivingThing)
// Adds: owner, guide()
Class:Create(GuideDog extends Dog) {
Var:String owner;
function setOwner(String o) {
owner = o;
}
function guide() {
energy = energy - 15;
Konsol:Print("${name} guides ${owner} (energy now ${energy} )");
}
}
// ── Demo ──────────────────────────────────────────────────────────────────────
Konsol:Print("--- LivingThing ---");
Class:LivingThing lt;
lt.init();
lt.breathe();
lt.status();
Konsol:Print("--- Animal ---");
Class:Animal a;
a.init();
a.setName("GenericAnimal");
a.breathe(); // inherited from LivingThing
a.move(); // Animal
a.status(); // overridden at Animal level
Konsol:Print("--- Dog ---");
Class:Dog dog;
dog.init();
dog.setName("Buddy");
dog.setBreed("Labrador");
dog.breathe(); // inherited from LivingThing (2 levels up)
dog.move(); // inherited from Animal
dog.fetch(); // Dog-only
dog.status(); // overridden at Dog level
Konsol:Print("--- GuideDog ---");
Class:GuideDog gd;
gd.init();
gd.setName("Lassie");
gd.setBreed("Collie");
gd.setOwner("John");
gd.breathe(); // inherited from LivingThing (3 levels up)
gd.move(); // inherited from Animal (2 levels up)
gd.fetch(); // inherited from Dog
gd.guide(); // GuideDog-only
gd.status(); // Dog's override (GuideDog didn't re-override it)
// 17_inherit_builtins.ks — Extending built-in modules via composition
//
// Built-in "classes" (Konsol, Math, String, File, Time) are C++ handler
// functions, not ClassDef objects, so you cannot write:
//
// Class:Create(MyMath extends Math) { ... } // NOT supported
//
// Instead, wrap them: create a user class whose methods delegate to the
// built-in calls internally. This is composition, and it's just as powerful.
Konsol:Print("=== Built-in Extension via Composition ===");
// ── Extended Math ─────────────────────────────────────────────────────────────
// Wraps Math: and adds Clamp, Lerp, Hypot, IsPrime
Class:Create(MathEx) {
function clamp(Number v, Number lo, Number hi) : Number {
if (v < lo) { return lo; }
if (v > hi) { return hi; }
return v;
}
function lerp(Number a, Number b, Number t) : Number {
return a + (b - a) * t;
}
function hypot(Number a, Number b) : Number {
Var:Number _ret = 0;
Math:Sqrt(a * a + b * b, _ret);
return _ret;
}
function isPrime(Number n) : Boolean {
if (n < 2) { return false; }
Var:Number i = 2;
while (i * i <= n) {
Var:Number rem = n % i;
if (rem == 0) { return false; }
i++;
}
return true;
}
function sign(Number n) : Number {
if (n > 0) { return 1; }
if (n < 0) { return -1; }
return 0;
}
}
Class:MathEx mx;
Konsol:Print("clamp(15, 0, 10) = ${mx.clamp(15, 0, 10)}");
Konsol:Print("clamp(-3, 0, 10) = ${mx.clamp(-3, 0, 10)}");
Konsol:Print("clamp( 5, 0, 10) = ${mx.clamp(5, 0, 10)}");
Konsol:Print("lerp(0, 100, 0.25) = ${mx.lerp(0, 100, 0.25)}");
Konsol:Print("hypot(3, 4) = ${mx.hypot(3, 4)}");
Konsol:Print("isPrime(7) = ${mx.isPrime(7)}");
Konsol:Print("isPrime(9) = ${mx.isPrime(9)}");
Konsol:Print("isPrime(13) = ${mx.isPrime(13)}");
Konsol:Print("sign(-5) = ${mx.sign(-5)}");
Konsol:Print("sign(0) = ${mx.sign(0)}");
Konsol:Print("sign(3) = ${mx.sign(3)}");
// ── Extended String ───────────────────────────────────────────────────────────
// Wraps String: and adds StartsWith, EndsWith, Repeat, PadLeft
Class:Create(StringEx) {
function startsWith(String s, String prefix) : Boolean {
Var:Number plen = 0;
Var:String head = "";
Var:Number cmp = 0;
String:Len(prefix, plen);
String:Left(s, plen, head);
String:Compare(head, prefix, cmp);
return cmp == 0;
}
function endsWith(String s, String suffix) : Boolean {
Var:Number slen = 0;
Var:String tail = "";
Var:Number cmp = 0;
String:Len(suffix, slen);
String:Right(s, slen, tail);
String:Compare(tail, suffix, cmp);
return cmp == 0;
}
function repeat(String s, Number n) : String {
Var:String result = "";
Var:Number i = 0;
while (i < n) {
result = result + s;
i++;
}
return result;
}
function isBlank(String s) : Boolean {
Var:String trimmed = "";
Var:Number tlen = 0;
String:Trim(s, trimmed);
String:Len(trimmed, tlen);
return tlen == 0;
}
}
Class:StringEx sx;
Konsol:Print("startsWith(hello, hel) = ${sx.startsWith("hello", "hel")}");
Konsol:Print("startsWith(hello, wor) = ${sx.startsWith("hello", "wor")}");
Konsol:Print("endsWith(hello, llo) = ${sx.endsWith("hello", "llo")}");
Konsol:Print("endsWith(hello, abc) = ${sx.endsWith("hello", "abc")}");
Konsol:Print("repeat(ab, 4) = ${sx.repeat("ab", 4)}");
Konsol:Print("isBlank('') = ${sx.isBlank("")}");
Konsol:Print("isBlank(' ') = ${sx.isBlank(" ")}");
Konsol:Print("isBlank(hi) = ${sx.isBlank("hi")}");
// ── Extended Logger ───────────────────────────────────────────────────────────
// Wraps Konsol: and adds a prefix, log levels, and timestamps
Class:Create(Logger) {
Var:String prefix;
Var:Boolean timestamps;
function setPrefix(String p) {
prefix = p;
}
function enableTimestamps() {
timestamps = true;
}
function info(String msg) {
if (timestamps == true) {
Time:GetHour(); Var:Number h = _ret;
Time:GetMinute(); Var:Number m = _ret;
Time:GetSecond(); Var:Number sec = _ret;
Konsol:Print("[INFO] ${h} : ${m} : ${sec} | ${prefix} ${msg}");
} else {
Konsol:Print("[INFO] ${prefix} ${msg}");
}
}
function warn(String msg) {
Konsol:Print("[WARN] ${prefix} ${msg}");
}
function err(String msg) {
Konsol:Print("[ERR ] ${prefix} ${msg}");
}
}
Konsol:Print("--- Logger ---");
Class:Logger log;
log.setPrefix("[App]");
log.info("starting up");
log.warn("low memory");
log.err("connection failed");
log.enableTimestamps();
log.info("timestamps enabled");