[Moose-commits] r7553 - in Mouse/trunk: lib t

sartak at code2.0beta.co.uk sartak at code2.0beta.co.uk
Thu Feb 5 03:47:44 GMT 2009


Author: sartak
Date: 2009-02-04 19:47:44 -0800 (Wed, 04 Feb 2009)
New Revision: 7553

Added:
   Mouse/trunk/t/042-override.t
Modified:
   Mouse/trunk/lib/Mouse.pm
Log:
Implement override/super

Modified: Mouse/trunk/lib/Mouse.pm
===================================================================
--- Mouse/trunk/lib/Mouse.pm	2009-02-05 02:23:53 UTC (rev 7552)
+++ Mouse/trunk/lib/Mouse.pm	2009-02-05 03:47:44 UTC (rev 7553)
@@ -23,7 +23,7 @@
 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(@_) }
 
@@ -77,6 +77,36 @@
     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;
 

Added: Mouse/trunk/t/042-override.t
===================================================================
--- Mouse/trunk/t/042-override.t	                        (rev 0)
+++ Mouse/trunk/t/042-override.t	2009-02-05 03:47:44 UTC (rev 7553)
@@ -0,0 +1,34 @@
+#!/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/;
+




More information about the Moose-commits mailing list