问题
Using Mason2. Have 3 components.
/Base.mc
/tmp/Base.mc
/tmp/index.mc
The /tmp/index.mc with a content:
hello from <% $m->request_path %></br>
<% $.Some %>
the $.Some is an method defined in the /Base.mc:
<%augment wrap><% inner() %></%augment>
<%method Some>
The default "Some" method defined in the <% __PACKAGE__ %>
</%method>
the /tmp/Base.mc contains only
<%augment wrap><% inner() %></%augment>
Requesting /tmp/index prints:
hello from /tmp/index
The default "Some" method defined in the MC0::Base_mc
Now added the Some method into /tmp/Base.mc
<%method Some>
Redefined "Some" method in <% __PACKAGE__ %>
</%method>
Requesting /tmp/index again, it prints:
hello from /tmp/index
Redefined "Some" method in MC0::tmp_Base_mc
It honored the redefined Some method in the wrapped /tmp/Base.mc
The question is:
If Mason allows redefine methods as above, what is the purpose of the <%override method>? Does the <%override Some> something differently? (when i tested, it prints the same).
EDIT Maybe the question can be reduced to the following perl code.
use 5.014;
use warnings;
package My;
use Moose;
sub some { say "some from " . __PACKAGE__ }
package My2;
use Moose;
extends 'My';
sub some { say "another some from " . __PACKAGE__ }
#the above line is an correct way to refefine a sub "some"?
#so don;t need to use the
#override 'some' => sub { say "another some from " . __PACKAGE__ };
package main;
use My2;
my $m = My2->new();
$m->some();
in both cases (e.g. "plain" redefine and redefine with "override") prints:
another some from My2
So, the only difference is the possibility of calling the super() in the some with override? and sorry if I missed some basic knowlegde... ;(
回答1:
override in Mason implements the method modifier override in Moose; Moose's override is syntactic sugar for the standard OO method for overriding a parent method, but with some restrictions if the method takes arguments. From the Moose docs for override:
override 'display_name' => sub { my $self = shift; return super() . q{, } . $self->title(); };The call to
super()is almost the same as calling$self->SUPER::display_name. The difference is that the arguments passed to the superclass's method will always be the same as the ones passed to the method modifier, and cannot be changed. All arguments passed tosuper()are ignored, as are any changes made to@_beforesuper()is called.
To give an example from your Moose classes above, let's give some some arguments:
package My;
use Moose;
sub some {
my $self = shift;
say " " . __PACKAGE__ . " method 'some' args: " . join " ", @_;
}
Output after creating a My object and calling $obj->some('pip', 'pop'):
My method 'some' args: pip pop
Now let's look at My2. Define some as a normal package method:
package My2;
use Moose;
extends 'My';
sub some {
my $self = shift;
say " # running 'some'";
say " " . __PACKAGE__ . " method 'some' args: " . join " ", @_;
@_ = reverse @_;
say " # running \$self->SUPER::some with no args";
$self->SUPER::some();
say " # running \$self->SUPER::some with reversed args";
$self->SUPER::some( @_ );
say " # running super() with no args";
super();
say " # running super() with reversed args";
super( @_ );
};
Create a My2 object, and call $obj->some('pip','pop'). Output:
# running 'some'
My2 method 'some' args: pip pop
# running $self->SUPER::some with no args
My method 'some' args:
# running $self->SUPER::some with reversed args
My method 'some' args: pop pip
# running super() with no args
# running super() with reversed args
Arguments passed to super() are ignored at test.pl line 29.
Things to note:
super()does nothing in a redefined method;super()cannot take arguments;$self->SUPER::somedoes not automatically get passed any arguments;- arguments to
$self->SUPER::somecan be altered.
Now redefine the some method using override:
override 'some' => sub {
my $self = shift;
say " # running 'some'";
say " " . __PACKAGE__ . " method 'some' args: " . join " ", @_;
@_ = reverse @_;
say " # running \$self->SUPER::some with no args";
$self->SUPER::some();
say " # running \$self->SUPER::some with reversed args";
$self->SUPER::some( @_ );
say " # running super() with no args";
super();
say " # running super() with reversed args";
super( @_ );
};
Output:
# running 'some'
My2 method 'some' args: pip pop
# running $self->SUPER::some with no args
My method 'some' args:
# running $self->SUPER::some with reversed args
My method 'some' args: pop pip
# running super() with no args
My method 'some' args: pip pop
# running super() with reversed args
Arguments passed to super() are ignored at test.pl line 29.
My method 'some' args: pip pop
Things to note:
- the
super()method now correctly calls the superclass methodsome; super()cannot take arguments; it automatically uses the same@_that you pass to the subclass method;- arguments to
$self->SUPER::somecan be altered.
It is basically up to you how you implement methods in your subclasses, but this should have illustrated the differences between override and standard method redefinition.
来源:https://stackoverflow.com/questions/25947199/mason-methods-scope-override