问题
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::some
does not automatically get passed any arguments;- arguments to
$self->SUPER::some
can 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::some
can 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