带有 Moo 的 Perl:如何调用超类的方法实现?

Perl with Moo: How to call superclass's implementation of a method?

我有一个 class X 和一个子 class YX 有一个方法 calculate(),我想在 Y 中用一些额外的行为覆盖它,一个 if 语句,如果失败,调用 X.calculate() .在 Python 中,这将通过以下方式完成:

class X(object):
    def calculate(self, my_arg):
        return "Hello!"

class Y(X):
    def calculate(self, my_arg):
        if type(my_arg) is int and my_arg > 5:
            return "Goodbye!"
        return super(Y, self).calculate(my_arg)

如何使用 Moo 模块在 Perl 中执行此操作?

这可以通过 SUPER:: pseudo-class 在 Perl 中完成,它是 Perl 方法解析系统的一部分。你只要把它放在 method-call 前面就行了。它不适用于 class 方法或函数调用。

use strict;
use warnings;
use feature 'say';

package Foo;
use Moo;

sub frobnicate {
    my $self = shift;
    say "foo";
}

package Bar;
use Moo;
extends 'Foo';

sub frobnicate {
    my $self = shift;
    say "bar";
    $self->SUPER::frobnicate;    
}

package main;
Bar->new->frobnicate;

如果您有 multi-level 继承,您甚至可以使用它来调用每个 parent 的方法。

package Grandparent;
sub foo { ... }

package Parent;
use parent 'Grandparent';
sub foo { $_[0]->SUPER::foo }

package Child;
use parent 'Parent';
sub foo { $_[0]->SUPER::foo }

这将随后在 Child、Parent 和 Grandparent 中调用 foo

正如 docs 指出的那样:

No support for super, override, inner, or augment - the author considers augment to be a bad idea, and override can be translated:

around foo => sub {
  my ($orig, $self) = (shift, shift);
  ...
  $self->$orig(@_);
  ...
};

(emphasis mine)

#!/usr/bin/env perl

use strict;
use warnings;

package X;

use Moo;

sub calculate {
    return 'Hello!'
}


package Y;

use Moo;

extends 'X';

around calculate => sub {
    my $orig = shift;
    my $self = shift;

    if ( $_[0] > 5 ) {
        return $self->$orig(@_);
    }

    return 'Goodbye!';
};

package main;

my $y = Y->new;

print $y->calculate(3), "\n";
print $y->calculate(11), "\n";