7

Moose::Manual::Attributes状态:

作为使用子例程引用 [默认] 的替代方法,您可以为您的属性提供一个构建器方法: ... 这有几个优点。首先,它将一大块代码移动到自己的命名方法中,这提高了可读性和代码组织。

因此,您的属性可以这样定义一个默认值:

has attr => (
  is => 'ro',
  builder => 'subroutine'
);
sub subroutine {
  # figure out and return default value
}

我不明白为什么这必须与默认值分开。您不能只传递对命名子例程的引用吗?

has attr => (
  is => 'ro',
  default => \&subroutine
);

这不是更好的编程实践吗,因为保证不会意外引用不存在的子例程?您将使用逻辑引用而不是符号引用来引用该方法。

4

3 回答 3

14

调用构建器时,会发生这种情况:

$object->$builder

如果 builder 是一个字符串(比如说build_attr),那么用户可以在子类中编写自己的 build_attr 方法,然后调用它。这使得默认值可以通过简单的命名方法机制进行扩展。

如果它是对子例程的引用,则该引用是在原始类的包中获取的,这意味着它不能以相同的方式被覆盖。

于 2009-02-18T16:15:00.197 回答
10

这不是一个“象征性”的参考。builder 是一个方法。这意味着它可以从角色继承和组合。如果您传递子例程引用,则该引用必须存在于同一包中(或完全限定)。

我很确定我在手册中对此进行了解释。不清楚吗?

于 2009-02-18T16:14:48.417 回答
7

子类化。

Builder 指定要调用的方法名称,因此

package Something;
use Moose;

extends 'YourClass';

sub subroutine { <some other default> }

会为“子程序”的构建器调用Something::subroutine,而如果您使用subref样式,则将调用YourClass::subroutine,因为您直接引用了子程序而不是让它通过方法派遣。

于 2009-02-18T16:15:35.717 回答