Classes and Objects

$.attr inside methods calls the accessor method (overridable). $!attr accesses the storage directly.

self refers to the invocant. Methods can name the invocant explicitly: method m($self: $arg) { }.

Class methods vs instance methods: any method can be called on the type object (BankAccount.count), but accessing attributes requires an instance.

class BankAccount {
    has Str $.owner is required;          # public read-only accessor: .owner
    has Numeric $.balance = 0;            # public with a default
    has @!transactions;                   # private attribute
    has $.overdraft-limit is rw = 0;      # public read-write accessor
    my $count = 0;                        # class-level (lexical) variable
    our $bank-name = 'Raku Bank';         # package variable

    method deposit(Numeric $amount where * > 0) {
        $!balance += $amount;             # $! accesses the attribute directly
        @!transactions.push: deposit => $amount;
        self                              # return self for chaining
    }

    method withdraw(Numeric $amount where * > 0) {
        die "Insufficient funds" if $amount > $!balance + $!overdraft-limit;
        $!balance -= $amount;
        @!transactions.push: withdraw => $amount;
        self
    }

    method history { @!transactions.List }
    method !audit { "private method: {@!transactions.elems} transactions" }   # private method
    method report { self!audit }          # call private methods with !

    method count { $count }
    submethod TWEAK { $count++ }          # r
…

21.1 Method Call Variants

say $acc.?nonexistent // 'no such method';  # .? returns Nil if the method doesn't exist
my $meth = 'deposit';
$acc."$meth"(10);                           # dynamic method name
my &m = BankAccount.^find_method('balance');
say m($acc);
say $acc.&{ $^obj.balance * 2 };            # call a block as a method
.deposit(5) given $acc;                     # topicalized call
$acc.deposit(1).deposit(2) andthen .say;