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;