Pome supports object-oriented programming through classes and objects.
Use the class keyword to define a class:
class Dog {
fun init(name) {
this.name = name;
this.sound = "Woof";
}
fun speak() {
print(this.name, "says", this.sound);
}
}
Create an object by calling the class like a function:
var dog = Dog("Buddy");
dog.speak(); // Output: Buddy says Woof
The init method is a constructor - it runs when an object is created:
class Person {
fun init(name, age) {
this.name = name;
this.age = age;
}
}
var person = Person("Alice", 30);
print(person.name); // Output: Alice
print(person.age); // Output: 30
Instance variables store data specific to each object. Access them with this:
class Counter {
fun init() {
this.count = 0;
}
fun increment() {
this.count = this.count + 1;
}
fun getCount() {
return this.count;
}
}
var c1 = Counter();
var c2 = Counter();
c1.increment();
c1.increment();
c2.increment();
print(c1.getCount()); // Output: 2
print(c2.getCount()); // Output: 1
Each object has its own set of instance variables.
Pome supports single inheritance using the extends keyword. A child class inherits all methods from its parent class.
class Animal {
fun init(name) {
this.name = name;
}
fun speak() {
print(this.name, "makes a sound.");
}
}
class Dog extends Animal {
fun speak() {
print(this.name, "barks.");
}
}
var dog = Dog("Buddy");
dog.speak(); // Output: Buddy barks.
Use super to call methods from the parent class:
class Base {
fun greet() {
print("Hello from Base");
}
}
class Derived extends Base {
fun greet() {
print("Derived starts greeting:");
super.greet();
}
}
var d = Derived();
d.greet();
// Output:
// Derived starts greeting:
// Hello from Base
Note: Calling super.init() is currently manual. It doesn't automatically chain in the constructor.
class Person {
fun init(name) {
this.name = name;
}
}
class Student extends Person {
fun init(name, school) {
super.init(name);
this.school = school;
}
}
Methods are functions defined inside a class.
- Constructors: The
initmethod is a special constructor that is called when a new instance is created. It automatically returnsthis, even if no return statement is present. - Instance Access: All methods receive
thisas an implicit first argument (handled automatically by the VM).
class Rectangle {
fun init(width, height) {
this.width = width;
this.height = height;
}
fun area() {
return this.width * this.height;
}
fun perimeter() {
return 2 * (this.width + this.height);
}
}
var rect = Rectangle(5, 10);
print(rect.area()); // Output: 50
print(rect.perimeter()); // Output: 30
this refers to the current object:
class Dog {
fun init(name) {
this.name = name;
}
fun introduce() {
print("I am " + this.name);
}
}
var dog = Dog("Max");
dog.introduce(); // Output: I am Max
Access object properties using dot notation:
class Person {
fun init(name) {
this.name = name;
}
}
var person = Person("Bob");
print(person.name); // Output: Bob
person.name = "Robert"; // Modify property
print(person.name); // Output: Robert
Methods can return this to enable chaining:
class Calculator {
fun init() {
this.result = 0;
}
fun add(x) {
this.result = this.result + x;
return this;
}
fun multiply(x) {
this.result = this.result * x;
return this;
}
fun getResult() {
return this.result;
}
}
var calc = Calculator();
var answer = calc.add(5).multiply(3).add(2).getResult();
print(answer); // Output: 17 ((5 * 3) + 2)
Classes are useful for maintaining state:
class BankAccount {
fun init(owner, balance) {
this.owner = owner;
this.balance = balance;
}
fun deposit(amount) {
this.balance = this.balance + amount;
print(this.owner, "deposited", amount);
}
fun withdraw(amount) {
if (amount > this.balance) {
print("Insufficient funds");
return false;
}
this.balance = this.balance - amount;
print(this.owner, "withdrew", amount);
return true;
}
fun getBalance() {
return this.balance;
}
}
var account = BankAccount("Alice", 1000);
account.deposit(500); // Alice deposited 500
account.withdraw(200); // Alice withdrew 200
print(account.getBalance()); // Output: 1300
While Pome doesn't enforce access modifiers (private/public), you can follow conventions.
class Stack {
fun init() {
this._items = []; // Convention: _items is private
}
fun push(value) {
this._items = this._items + [value];
}
fun pop() {
if (len(this._items) == 0) {
return nil;
}
var item = this._items[-1];
this._items = this._items[:len(this._items)-1];
return item;
}
fun isEmpty() {
return len(this._items) == 0;
}
}
var stack = Stack();
stack.push(1);
stack.push(2);
print(stack.pop()); // Output: 2
print(stack.pop()); // Output: 1
print(stack.isEmpty()); // Output: true
Objects can contain other objects:
class Engine {
fun init(horsepower) {
this.horsepower = horsepower;
}
}
class Car {
fun init(brand, engine) {
this.brand = brand;
this.engine = engine;
}
fun getHorsepower() {
return this.engine.horsepower;
}
}
var engine = Engine(300);
var car = Car("Ferrari", engine);
print(car.getHorsepower()); // Output: 300
Use type() to check an object's type:
class MyClass {
fun init() {
}
}
var obj = MyClass();
print(type(obj)); // Output: instance
To check the class name, access the class through the instance:
// Note: Pome doesn't have direct class name introspection
// You can store the class name as a property:
class Dog {
fun init(name) {
this.name = name;
this._className = "Dog";
}
}
var dog = Dog("Rex");
print(dog._className); // Output: Dog
class Temperature {
fun init(celsius) {
this._celsius = celsius;
}
fun getCelsius() {
return this._celsius;
}
fun getFahrenheit() {
return this._celsius * 9 / 5 + 32;
}
fun setCelsius(value) {
this._celsius = value;
}
}
var temp = Temperature(0);
print(temp.getCelsius()); // Output: 0
print(temp.getFahrenheit()); // Output: 32
temp.setCelsius(100);
print(temp.getFahrenheit()); // Output: 212
class Point {
fun init(x, y) {
this.x = x;
this.y = y;
}
fun distanceFromOrigin() {
var dx = this.x;
var dy = this.y;
return (dx * dx + dy * dy) ^ 0.5;
}
}
// Create points
var p1 = Point(3, 4);
print("Distance from origin:", p1.distanceFromOrigin()); // Output: Distance from origin: 5
Pome doesn't have built-in object comparison, but you can implement it:
class Color {
fun init(r, g, b) {
this.r = r;
this.g = g;
this.b = b;
}
fun equals(other) {
return this.r == other.r and
this.g == other.g and
this.b == other.b;
}
}
var c1 = Color(255, 0, 0);
var c2 = Color(255, 0, 0);
var c3 = Color(0, 255, 0);
print(c1.equals(c2)); // Output: true
print(c1.equals(c3)); // Output: false
-
Use meaningful class names:
BankAccountis clearer thanBA -
Initialize all properties in init: Prevents undefined property errors
class Dog { fun init(name) { this.name = name; this.age = 0; // Initialize here } } -
Keep classes focused: A class should represent one concept
-
Use method names that describe actions:
withdraw()notw() -
Consider composition over complex inheritance patterns
-
Document the expected behavior: Use comments for non-obvious methods
// Removes and returns the top item fun pop() { // ... }
Next: Collections
Back to: Documentation Home