【问题标题】:Simplified default parameters handling within a perl OO package在 perl OO 包中简化默认参数处理
【发布时间】:2011-10-04 11:31:34
【问题描述】:

这是我所拥有的重要子集:

sub logger {
    my $self = shift;
    my %def =  (
        type => $self->{options}{name}, 
        severity => 1,
        date => $self->now(),
        message => ''  
    );
    my %opt = %def;
    if ( my $ref = shift ) {
        %opt = (%def, %{$ref});
    }
    croak('message is a required option') if $opt{message} eq '';
    warn($opt{type} . ': ' . $opt{message} . "\n") if ( $self->{_verbose} );
    # Do some other interesting things.
}

那么我可以这样称呼它:

$op->logger({message => 'Some message'});

因此,如果我的任何参数丢失,它们将获得我在 %def 哈希中指定的默认值。如果缺少必需的参数,我会死。

它的基础是我用用户指定的内容重载了 def 哈希。

    if ( my $ref = shift ) {
        %opt = (%def, %{$ref});
    }

问题是他们可以指定我的选项列表之外的东西,或者发送一个哈希而不是一个哈希引用,或者一个标量,或者 undef,或者许多其他方式这可能会爆炸。

我确信有一种更优雅的方式来处理这个问题。
我似乎想起了一些使用 ref() 的代码,如果没有传入任何内容,这些代码就不会崩溃。

【问题讨论】:

    标签: perl oop perl-module


    【解决方案1】:

    Method::Signatures 完全符合您的要求,并且非常优雅

    method logger (
        :$type     = $self->{options}{name},
        :$severity = 1,
        :$date     = $self->now,
        :$message! # No default and required, so croaks if not provided by caller.
    ) {
        my %opt = (
            type     => $type, 
            severity => $severity,
            date     => $date,
            message  => $message
        );
        # Do some other interesting things.
    }
    

    签名中的冒号指定命名参数(作为散列传递)。 $message 后面的感叹号是必需的。

    【讨论】:

    • 我实际上采用了 MooseX::Method::Signatures 的方式,但是你得到了勾号,因为你给出了一个链接和一个例子,所以你把我带到了它。谢谢。
    • Groovy,虽然Method::SignaturesMoose 兼容并支持Moose 的类型约束。另请参阅同一发行版中的 Method::Signatures::Modifiers
    【解决方案2】:

    处理这一切的优雅方式都方便地捆绑在 Moose 中,如果 Moose 对你来说太重,甚至是 Mouse 或 Moo。

    【讨论】:

      【解决方案3】:

      我想我会做这样的事情。尽管毫无疑问,有很多 CPAN 模块可以让这变得更简单。

      sub logger {
          my $self = shift;
      
          # Set $ref to an empty hash ref if it's not given.
          # This makes a lot of later code far simpler
          my $ref = shift || {};
      
          # Check you have a hash ref
          unless (ref $ref eq 'HASH') {
              die "Argument to logger must be a hash ref";
          }
      
          my %def =  (
              type => $self->{options}{name}, 
              severity => 1,
              date => $self->now(),
              message => '',
          );
      
      
          my %opt = (%def, %$ref);
      
          # Now check we only have valid options. Assume that all valid
          # keys are in %def
          foreach (keys %opt) {
              delete $opt{$_} unless exists $def{$_};
          }
      
          croak('message is a required option') if $opt{message} eq '';
          warn($opt{type} . ': ' . $opt{message} . "\n") if ( $self->{_verbose} );
          # Do some other interesting things.
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-09-15
        • 2015-02-25
        • 1970-01-01
        • 2013-06-16
        相关资源
        最近更新 更多