use CLOS;
class Bake {
method preheat {
say "preheating";
}
method cook {
say "cooking";
}
method rest {
say "resting";
}
}
class Cook is Bake {
method preheat is before {
say "...about to preheat";
}
method rest is after {
say "...resting done";
}
}
my $cook = Cook.new;
$cook.preheat;
say "----";
$cook.cook;
say "----";
$cook.rest;
####
perl6 -I . Bake.pm
...about to preheat
preheating
----
cooking
----
resting
...resting done
##
##
my class CLOSClassHOW is Metamodel::ClassHOW {
my Bool %before{Any};
my Bool %after{Any};
multi sub trait_mod:(Routine $r, :$before!) is export {
%before{$r} = True;
}
multi sub trait_mod:(Routine $r, :$after!) is export {
%after{$r} = True;
}
#| find this method in our parents
method !find-super-method($obj, $name, *@etc) {
my @mro = self.mro($obj);
@mro.shift; # skip ourselves
for @mro {
my %methods = $_.HOW.method_table($_);
return %methods{$name}
if %methods{$name}:exists;
}
}
method find_method($obj, $name) {
my $raw-meth := callsame;
my $meth := $raw-meth;
if $raw-meth.defined && (%before{$raw-meth} || %after{$raw-meth}) {
my $next-meth := self!find-super-method($obj,$name);
$meth := -> $c, |args {
$raw-meth($obj, |args) if %before{$raw-meth};
my $result := $next-meth($obj, |args)
if $next-meth.defined ;
$raw-meth($obj, |args) if %after{$raw-meth};
$result;
}
}
$meth;
}
method publish_method_cache($obj) {
# no caching, so we always hit find_method
}
}
my module EXPORTHOW { }
EXPORTHOW.WHO. = CLOSClassHOW;