除非传递的构造函数参数是一个哈希类型,否则会对无效参数产生影响?

时间:2013-07-11 15:43:47

标签: perl oop hash constructor hashref

对于将某些参数传递给构造函数类型的不同方法,我有点模糊不清。我想只传递哈希引用\%hash或列表foo => 1, bar => 1但不能同时传递croak,如果还有其他内容通过,( single elements, array reference )

例如,我传递了我的引用或列表.. (This works for the way I do this)

my $obj = foo->new;
my $data = $obj->dump( \%hash );
my $data = $obj->dump( foo => 1, bar => 1 );

my $obj = foo->dump( \%hash );
my $obj = foo->dump( foo => 1, bar => 1 );

包装模块:

package foo;

use strict;
use Carp;

use Scalar::Util qw/reftype/;

sub new { return bless {}, shift }

sub dump {
   my $class = shift;
   my $self  = shift;
   unless ( reftype( $self ) eq reftype {} ) {
         croak("Constructor method not a hash type!");
   }
}

1;

我也考虑过在这里使用条件运算符? :,但我无法正确地将其误解。

my $self  = reftype($_[0]) eq reftype {} ? shift : {@_};

有更好的首选方法吗?

2 个答案:

答案 0 :(得分:2)

我们可以查看可以调用dump方法的各种方法。

如果我们传递“哈希列表”,则元素数量是偶数(@_ % 2 == 0)。此外,如果存在至少一个键值对,则第一个参数(键)是一个字符串,因此not defined reftype $_[0]成立。

如果我们传递一个哈希引用,那么参数列表应该只保存这个引用,而不是其他值:@_ == 1。第一个参数是哈希:reftype($_[0]) eq 'HASH'

因此,要将参数放在哈希引用中,可以执行以下操作:

sub dump {
  my $invocant = shift;
  my $hashref;
  if (@_ == 1 and reftype $_[0] eq 'HASH') {
    $hashref = $_[0];
  } elsif (@_ % 2 == 0 and (@_ == 0 or not defined reftype $_[0])) {
    $hashref = +{ @_ };
  } else {
    croak "Unknown argument format: either pass a hashref, or an even-valued list";
  }
  ...; # do something with $hashref
}

要确定$invocant是否是类名或对象,只需询问它是否有福:

if (defined Scalar::Util::blessed $invocant) {
  say "Yep, it is an object";
} else {
  say "Nope, it is a package name";
}

答案 1 :(得分:2)

没有“哈希列表”这样的东西。 foo => 1, bar => 1,只是一个四元素列表。听起来你想接受散列引用甚至是args的数量。

sub dump {
   my $self = shift;
   my %args;
   if (@_ == 1) {
      croak("...") if (ref($_[0]) // '') ne 'HASH';
      %args = %{ $_[0] };
   } else {
      croak("...") if @_ % 2 != 0;
      %args = @_;
   }

   ...
}