尝试了解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>
......同样的结果。当设计&#34;模型(对象层次结构)&#34; - 根据我应该决定何时使用around
和何时使用augment
?
这可能是我目前还不了解的其他(更深层次的)事物。
可以请某人提供更深入的&#34;解释,因为阅读tru Moose/Manual/MethodModifiers显然没有足够的帮助......
答案 0 :(得分:5)
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
无法在角色中工作(检查超类的包绑定的概念是什么编译时,$self->SUPER::method(@args)
会检查角色的超类(即无),而不是消耗角色的类的超类。如果你不是使用角色,然后SUPER
仍然可以在Moose类中使用.TLDR:SUPER
被角色打破,所以Moose会给你around
作为替代。
要比较的另一件事是override
,它有点像around
,但是为您提供了这个super()
函数,它可能比$self->$orig(@_)
稍微清晰一些。它还具有"there can be only one"功能。如果两个角色试图为同一个方法提供around
修饰符,那很好:它们都可以包装方法(尽管它们的应用顺序是未定义的)。如果两个角色尝试提供override
修饰符,那就是错误。
augment
的实施在我的经历中有点脆弱,所以在我的书中是避免它的理由。不要试图用around
替换它,因为它们确实做了不同的事情。而是用我上面第一个例子中使用的模式替换它。
答案 1 :(得分:1)
使用around
应始终是您的第一直觉。作为(Moose创作者)Stevan Little says about augment
:
值得庆幸的是,只有一小部分人真正了解这一点 功能和那些人中只有少数人疯狂到 尝试使用它。