use Mouse::Object;
use Mouse::Util::TypeConstraints;
-our @EXPORT = qw(extends has before after around blessed confess with);
+our @EXPORT = qw(extends has before after around override super blessed confess with);
sub extends { Mouse::Meta::Class->initialize(caller)->superclasses(@_) }
Mouse::Util::apply_all_roles((caller)[0], @_);
}
+our $SUPER_PACKAGE;
+our $SUPER_BODY;
+our @SUPER_ARGS;
+
+sub super {
+ # This check avoids a recursion loop - see
+ # t/100_bugs/020_super_recursion.t
+ return if defined $SUPER_PACKAGE && $SUPER_PACKAGE ne caller();
+ return unless $SUPER_BODY; $SUPER_BODY->(@SUPER_ARGS);
+}
+
+sub override {
+ my $meta = Mouse::Meta::Class->initialize(caller);
+ my $pkg = $meta->name;
+
+ my $name = shift;
+ my $code = shift;
+
+ my $body = $pkg->can($name)
+ or confess "You cannot override '$name' because it has no super method";
+
+ $meta->add_method($name => sub {
+ local $SUPER_PACKAGE = $pkg;
+ local @SUPER_ARGS = @_;
+ local $SUPER_BODY = $body;
+
+ $code->(@_);
+ });
+}
+
sub import {
my $class = shift;
--- /dev/null
+#!/usr/bin/env perl
+use strict;
+use warnings;
+use Test::More tests => 3;
+use Test::Exception;
+
+my @parent_calls;
+my @child_calls;
+
+do {
+ package Parent;
+ sub foo { push @parent_calls, [@_] }
+
+ package Child;
+ use Mouse;
+ extends 'Parent';
+
+ override foo => sub {
+ my $self = shift;
+ push @child_calls, [splice @_];
+ super;
+ };
+};
+
+Child->foo(10, 11);
+is_deeply([splice @parent_calls], [[Child => 10, 11]]);
+is_deeply([splice @child_calls], [[10, 11]]);
+
+throws_ok {
+ package Orphan; # :(
+ use Mouse;
+ override foo => sub { };
+} qr/^You cannot override 'foo' because it has no super method/;
+