【问题标题】:Why does Moose's builder take a string value?为什么 Moose 的 builder 取一个字符串值?
【发布时间】:2023-03-18 13:50:01
【问题描述】:

Moose::Manual::Attributes 状态:

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

所以,你的属性可以这样定义一个默认值:

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

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

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

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

【问题讨论】:

    标签: perl moose


    【解决方案1】:

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

    $object->$builder
    

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

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

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

      • 嗯,我知道这不是 Perl 意义上的引用;由于我提到的原因,我只是在想更好的编程实践是传递对命名子例程的真实引用。但是,您是对的;手册的其余部分确实说明了为什么这种方式是可取的......
      • 请注意以“这有几个优点。首先...”开头的段落;也许将下一部分的一些内容移到那里进行跟进可能会有所帮助,因此该段落不仅提供了一个优势,而且对于那些想知道的人来说会更快。
      【解决方案3】:

      子类化。

      Builder 指定要调用的方法名,所以

      package Something;
      use Moose;
      
      extends 'YourClass';
      
      sub subroutine { <some other default> }
      

      会有Something::subroutine调用'subroutine'的构建器,而如果你使用subref风格,那么YourClass::subroutine会被调用,因为你直接引用了子程序而不是让它通过方法调度。

      【讨论】:

        猜你喜欢
        • 2016-05-21
        • 1970-01-01
        • 2021-11-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-10-04
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多