Language Guide
Object-Oriented Programming

Object-Oriented Programming

Flowa supports object-oriented programming with classes, inheritance, and method calls.

Classes

Classes support methods and instance properties:

class User {
    func init(name) {
        this.name = name;
    }
 
    func greet() {
        print("Hello, " + this.name);
    }
}
 
let user = new User("Alice");
user.greet();         // Hello, Alice
print(user.name);     // Alice

Constructors (init)

The init method is automatically called when a new instance is created with the new keyword. All arguments passed to new ClassName(...) are forwarded to the init method.

class Point {
    func init(x, y) {
        this.x = x;
        this.y = y;
    }
 
    func distance() {
        return sqrt(this.x * this.x + this.y * this.y);
    }
}
 
let point = new Point(3, 4);
print(point.distance());  // 5

Inheritance

Flowa supports single inheritance using either the extends keyword or < operator:

// Using 'extends' keyword (recommended)
class Admin extends User {
    func init(name, role) {
        super.init(name);  // Call parent constructor
        this.role = role;
    }
 
    func info() {
        print(this.name + " is an " + this.role);
    }
}
 
// Alternative syntax using '<' operator
class Manager < User {
    func init(name) {
        super.init(name);
    }
}

Inheritance Features:

  • Use extends keyword or < operator for inheritance
  • Use super.methodName(...) to call parent class methods
  • Use super.init(...) to call parent constructor
  • Child classes inherit all methods and can override them

Method Overriding

Child classes can override parent methods:

class Animal {
    func init(name) {
        this.name = name;
    }
 
    func speak() {
        print(this.name + " makes a sound");
    }
}
 
class Dog extends Animal {
    func speak() {
        print(this.name + " barks");
    }
}
 
let dog = new Dog("Buddy");
dog.speak();  // Buddy barks

Complete Example

class Person {
    func init(name, age) {
        this.name = name;
        this.age = age;
    }
 
    func introduce() {
        return "I'm " + this.name + ", " + tostring(this.age) + " years old";
    }
}
 
class Student extends Person {
    func init(name, age, school) {
        super.init(name, age);
        this.school = school;
    }
 
    func introduce() {
        let intro = super.introduce();
        return intro + " and I study at " + this.school;
    }
}
 
let student = new Student("Alice", 20, "University");
print(student.introduce());
// I'm Alice, 20 years old and I study at University

Practical Examples

Bank Account

class BankAccount {
    func init(owner, balance) {
        this.owner = owner;
        this.balance = balance;
    }
 
    func deposit(amount) {
        this.balance = this.balance + amount;
        return this.balance;
    }
 
    func withdraw(amount) {
        if (amount > this.balance) {
            throw "Insufficient funds";
        }
        this.balance = this.balance - amount;
        return this.balance;
    }
 
    func getBalance() {
        return this.balance;
    }
}
 
let account = new BankAccount("Alice", 1000);
account.deposit(500);
print(account.getBalance());  // 1500

HTTP Router

class Router {
    func init() {
        this.routes = {};
    }
 
    func addRoute(method, path, handler) {
        let key = method + ":" + path;
        this.routes[key] = handler;
    }
 
    func handle(method, path, req, res) {
        let key = method + ":" + path;
        if (key in this.routes) {
            return this.routes[key](req, res);
        }
        res.writeHead(404);
        res.end("Not Found");
    }
}
 
class APIRouter extends Router {
    func init() {
        super.init();
        this.prefix = "/api";
    }
 
    func handle(method, path, req, res) {
        return super.handle(method, this.prefix + path, req, res);
    }
}

Best Practices

1. Use Meaningful Class Names

// Good
class UserAccount { ... }
 
// Avoid
class UA { ... }

2. Keep Classes Focused

// Good - single responsibility
class EmailValidator {
    func validate(email) { ... }
}
 
// Avoid - too many responsibilities
class UserManager {
    func validate() { ... }
    func sendEmail() { ... }
    func processPayment() { ... }
}

3. Use Inheritance Appropriately

// Good - clear "is-a" relationship
class Admin extends User { ... }
 
// Avoid - forced inheritance
class EmailSender extends User { ... }  // EmailSender is not a User

Next Steps