试图理解 Moose:
use Modern::Perl;
package FOO {
use Moose;
sub rep { say " <report></report>"; }
sub doc {
say "<document>";
inner();
say "</document>";
}
}
package BAR {
use Moose;
extends 'FOO';
around 'rep' => sub {
my $orig = shift;
my $self = shift;
say "<document>";
$self->$orig(@_);
say "</document>";
};
augment 'doc' => sub {
say " <report></report>";
};
}
package main {
BAR->new->rep;
say "===";
BAR->new->doc;
}
生产...
<document>
<report></report>
</document>
===
<document>
<report></report>
</document>
...同样的结果。在设计“模型(对象层次结构)”时 - 基于我应该决定何时使用
around
当augment
?这可能是我目前还不了解的其他(更深层次)的东西。
请有人提供“更深入”的解释,因为阅读真正的Moose/Manual/MethodModifiers显然没有足够的帮助......
最佳答案
augment
和 around
做的事情完全不同。 augment
旨在使这种模式更容易:
package Document {
use Moose;
sub make_document {
my $self = shift;
return "<doc>" . $self->_document_innards . "</doc>"
}
# stub; override in child class
sub _document_innards {
my $self = shift;
return "";
}
}
package Invoice {
use Moose;
extends 'Document';
sub _document_innards {
my $self = shift;
return "Give me money!";
}
}
使用
augment
它变成:package Document {
use Moose;
sub make_document {
my $self = shift;
return "<doc>" . inner() . "</doc>"
}
}
package Invoice {
use Moose;
extends 'Document';
augment make_document => sub {
my $self = shift;
return "Give me money!";
};
}
另一方面,
around
被用作 $self->SUPER::method(@args)
的替代品,因为 SUPER
不能在角色中工作(检查父类(super class)的包的概念是在编译时绑定(bind)的,因此 $self->SUPER::method(@args)
将检查 角色 的父类(super class)(即无)而不是消耗角色 的 类的父类(super class)。如果你不使用角色,那么 SUPER
仍然可以在 Moose 类中使用就好了。TLDR:SUPER
被角色破坏,所以 Moose 给你 around
作为替代。要比较的另一件事是
override
,它有点像 around
,但为您提供了这个 super()
函数,它可能比 $self->$orig(@_)
稍微干净一些。它还具有 "there can be only one" 功能。如果两个角色尝试为同一个方法提供 around
修饰符,那很好:它们都可以包装该方法(尽管应用它们的顺序是未定义的)。如果两个角色尝试提供 override
修饰符,那就是错误。根据我的经验,
augment
的实现有点脆弱,所以在我的书中是避免它的理由。不要尝试用 around
替换它,因为它们做的事情完全不同。相反,将其替换为我上面第一个示例中使用的模式。
关于Perl Moose 增强对比,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22557427/