Skip to content
Kavachकवच

Extend

Also known as: extend extension method monkey patch add method to existing type implement interface for

● Intermediate4 minBefore this: MethodsSpec 2.5

extend adds methods to a type you didn't write: a built-in type, a union, or a type from another module.

extend String {
    fn shout(self) -> String {
        self.upper() + "!"
    }
}

fn main() {
    print("namaste".shout())
}

The program ran and printed:

kavach run extend.kav

NAMASTE!
extend.kav: Kavach code, then what running it prints
type Status = Pending | Paid

extend Status {
    fn label(self) -> String {
        match self {
            Status.Pending => "waiting for payment"
            Status.Paid => "done"
        }
    }
}

extend Int {
    fn is_even(self) -> Bool {
        self % 2 == 0
    }
}

fn main() {
    print(Status.Paid.label())
    print(10.is_even())
}

The program ran and printed:

kavach run extend-more.kav

donetrue
extend-more.kav: Kavach code, then what running it prints

Inside extend, methods are written as in a record, with self. A union's methods go in an extend too, since a union has no body of its own.

Extending a generic type

To extend a generic type, name its parameters after extend, as a generic function does: extend<S> App<S>. So a type's many methods can be spread over files:

use routes

pub type App<S> {
    pub state: S
    pub routes: Int = 0
}

The program ran and printed:

kavach run

2 routes, state: orders1 route, state: 42
src/lib.kav and 2 more files: Kavach code, then what running it prints
  • S stands for the type's own parameter: state_of gives a String for one app and an Int for the other.
  • A name after extend that isn't one of the type's parameters is an error.
tested

Keeping a promise for another type

extend Rect: Describe { … } says that Rect, declared elsewhere, keeps the Describe interface:

interface Describe {
    fn describe(self) -> String
}

type User: Describe {
    name: String

    fn describe(self) -> String { "User {self.name}" }
}

type Rect {
    width: Int
    height: Int
}

extend Rect: Describe {
    fn describe(self) -> String { "Rect {self.width}x{self.height}" }
}

fn show<T: Describe>(item: T) -> String {
    item.describe()
}

fn main() {
    print(show(User(name: "Asha")))
    print(show(Rect(width: 2, height: 3)))
}

The program ran and printed:

kavach run interfaces.kav

User AshaRect 2x3
interfaces.kav: Kavach code, then what running it prints

extend adds methods, never fields: a type's data is always where the type is declared.