Red*_*ick 1 oop parameters perl idioms
在Perl中,如果我想在对象构造函数中使用命名参数,如果我希望进行一些验证,我的代码似乎有点笨拙.
sub new {
my $class = shift;
my $self = {};
my %args = @_;
foreach my $argname (keys %args) {
if ($argname eq 'FOO') { $self->{$argname} = $args{$argname}; }
elsif ($argname eq 'BAR') { $self->{$argname} = $args{$argname}; }
elsif ($argname eq 'BAZ') { $self->{$argname} = $args{$argname}; }
…
else { die "illegal argument $argname\n"; }
}
bless $self;
return $self;
}
Run Code Online (Sandbox Code Playgroud)
首先,有一个临时的hash(%args)似乎有点笨拙.其次,整个if链条似乎冗长乏味.
后者可以简化为
if ('-FOO-BAR-BAZ-'=~m/-$argname-/) { $self->{$argname} = $args{$argname} }
else { die "..."; }
Run Code Online (Sandbox Code Playgroud)
但我想这可以改进.
如果我需要检查值,if … elsif链仍然是必要的吗?
我搜索了一下但找不到更好的成语.有没有(除了使用某种Perl OO框架)
我发现自己不断编写不必要的代码来检查给定的参数.但后来我发现了Params :: Validate.它易于使用,如果验证失败,它提供非常清晰和用户友好的错误消息.涵盖所有可能的参数组合及其错误消息是一项繁琐的工作.我更喜欢这种方式:
use Params::Validate qw/:all/;
sub new {
my $pkg = shift;
validate(
@_, {
foo => { type => SCALAR | ARRAYREF },
bar => { type => SCALAR, optional => 1},
baz => { type => ARRAYREF, default => ['value'] },
quux => { isa => 'CGI' }
}
);
return bless { @_ }, $pkg;
}
Run Code Online (Sandbox Code Playgroud)
后来这段代码
MyApp::Something->new(
foo => 123,
bbr => 'typo',
quux => CGI->new()
);
Run Code Online (Sandbox Code Playgroud)
变为:
The following parameter was passed in the call to MyApp::Something::new but was not listed in the validation options: bbr
at test.pl line 14.
MyApp::Something::new(undef, 'foo', 123, 'bbr', 'typo', 'quux', 'CGI=HASH(0x7fd4fa1857e0)') called at test.pl line 27
Run Code Online (Sandbox Code Playgroud)