Perl - 如何创建接受各种数据类型的函数

时间:2015-01-20 13:35:32

标签: perl function inheritance polymorphism subroutine

在一些perl函数中,我希望能够处理各种类型的参数,当然还要区别对待它们。现在我正在使用此ref函数,并根据ref结果执行相应的代码部分,例如

sub method_that_accept_various_data_types(){
  if (ref $_[0] eq "ARRAY"){
    # ...
  }
  elsif (ref $_[0] eq "SCALAR"){
    # ...
  }
  elsif (ref $_[0] eq "HASH"){
    # ...
  }
}

是否有一些优雅的方式可以说我的所有功能都应遵循这种模式,或者我必须在所有子程序的开头使用提到的代码?我正在编写程序代码,类似的东西是OOP中的多态和继承,但我是这方面的新手。

修改 所有答案都需要将代码附加到所有新创建的函数。我问的是,对于现在定义的每个函数,是否有一些通用的方法,而不需要为新函数添加代码。

4 个答案:

答案 0 :(得分:1)

你也可以使用函数/调度表的散列,但它基本上是相同的方法,

sub method_that_accept_various_data_types {

  my $ref = ref($_[0]);

  my $func = {
    ARRAY => sub {
      print "$ref\n";
    },
    SCALAR => sub {
      print "$ref\n";
    },
    HASH => sub {
      print "$ref\n";
    },
  }->{$ref} or return;

  $func->(@_);
}

答案 1 :(得分:0)

您可以使用Switch module

中的switch声明
use Switch;

sub polymorph_function {
    my ($arg1, $arg2, ...) = @_;

    switch (ref $arg1) {
        case 'ARRAY' { ... }
        case 'HASH'  { ... }
        ...
    }
}

答案 2 :(得分:0)

我是基于Сухой27的例子添加这个作为额外的答案,因为我个人认为这是错误的代码。但如果你喜欢短代码,你可能会喜欢它:

sub polymorph_function {
    ({
        ARRAY => sub { ... },
        HASH  => sub { ... },
        ...
    }->{ref $_[0]} || return)->(@_);
}

它基本相同,只是没有临时变量。它创建一个匿名哈希,并直接取消引用其引用,并根据ref $_[0](第一个参数的类型)选择适当的密钥。然后立即使用原始子的所有参数调用对其中一个subs的结果coderef。

答案 3 :(得分:-1)

我只想过将大部分代码移到中心位置的方法。

sub polymorph_function {
    poly \@_, (
        ARRAY => sub { ... },
        HASH  => sub { ... },
        ...
    );
}

sub poly {
    my ($args, %subs) = @_;

    my $sub = $subs{ref $args->[0]} or return;
    $sub->( @$args );
}