首页 文章

梅森方法范围 - 覆盖

提问于
浏览
4

使用Mason2 . 有3个组件 .

/Base.mc
/tmp/Base.mc
/tmp/index.mc

/tmp/index.mc 内容如下:

hello from <% $m->request_path %></br>
<% $.Some %>

$.Some/Base.mc 中定义的方法:

<%augment wrap><% inner() %></%augment>

<%method Some>
The default "Some" method defined in the <% __PACKAGE__ %>
</%method>

/tmp/Base.mc 仅包含

<%augment wrap><% inner() %></%augment>

请求 /tmp/index 打印:

hello from /tmp/index
The default "Some" method defined in the MC0::Base_mc

现在将 Some 方法添加到 /tmp/Base.mc

<%method Some>
Redefined "Some" method in <% __PACKAGE__ %>
</%method>

再次请求 /tmp/index ,它打印:

hello from /tmp/index
Redefined "Some" method in MC0::tmp_Base_mc

它尊重重新定义的 Some 方法包裹 /tmp/Base.mc

问题是:

如果Mason允许重新定义上述方法,那么 <%override method> 的目的是什么? <%override Some> 有什么不同之处吗? (当我测试时,它打印相同) .

EDIT 也许问题可以简化为以下perl代码 .

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();

在这两种情况下(例如“普通”重新定义并重新定义“覆盖”)打印:

another some from My2

那么,唯一的区别是 someoverride 一起调用 super() 的可能性?如果我错过了一些基本的知识,我很抱歉...;(

1 回答

  • 4

    Mason中的 override 在Moose中实现方法修饰符 override ; Moose的 override 是覆盖父方法的标准OO方法的语法糖,但如果方法接受参数则有一些限制 . 来自Moose docs for override

    覆盖'display_name'=> sub {
    我的$ self = shift;
    return super() . q {,} . $自我> Headers (); };
    对super()的调用几乎与调用$ self-> SUPER :: display_name相同 . 不同之处在于传递给超类方法的参数将始终与传递给方法修饰符的参数相同,并且无法更改 . 传递给super()的所有参数都被忽略,调用super()之前对@_所做的任何更改都会被忽略 .

    举一个上面的Moose类的例子,让我们给出 some 一些参数:

    package My;
    use Moose;
    sub some {
        my $self = shift;
        say "   " . __PACKAGE__ . " method 'some' args: " . join " ", @_;
    }
    

    创建 My 对象并调用 $obj->some('pip', 'pop') 后输出:

    My method 'some' args: pip pop
    

    现在让我们来看看My2 . 将 some 定义为常规包方法:

    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( @_ );
    };
    

    创建一个 My2 对象,然后调用 $obj->some('pip','pop') . 输出:

    # 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.
    

    注意事项:

    • super() 在重新定义的方法中没有任何作用;

    • super() 不能参数;

    • $self->SUPER::some 不会自动传递任何参数;
      $self->SUPER::some

    • 参数可以更改 .

    现在使用 override 重新定义 some 方法:

    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( @_ );
    };
    

    输出:

    # 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
    

    注意事项:

    • super() 方法现在可以正确调用超类方法 some ;

    • super() 不能参数;它会自动使用您传递给子类方法的 @_ ;
      $self->SUPER::some

    • 参数可以更改 .

    这基本取决于您如何在子类中实现方法,但这应该说明 override 和标准方法重新定义之间的差异 .

相关问题