建立Does Perl have an enumeration type?,如何执行动态类型检查(或者如果use strict能够执行静态类型检查)我的子例程参数是否获得了正确的枚举类型?
package Phone::Type;
use constant {
HOME => 'Home',
WORK => 'Work',
};
package main;
sub fun
{
my ($my_phone_type_enum) = @_;
# How to check my_phone_type_enum, is either Phone::Type->HOME or Phone::Type->WORK or ... but not 'Dog' or 'Cat'?
}
fun(Phone::Type->HOME); # valid
fun(Phone::Type->WORK); # valid
fun('DOG'); # run-time or compile time error
答案 0 :(得分:4)
这是一种方式:
#!/usr/bin/perl
package Phone::Type;
use strict;
use warnings;
use constant {
HOME => 'Home',
WORK => 'Work',
};
package main;
use strict;
use warnings;
sub fun {
my ($phone_type) = @_;
Phone::Type->can( $phone_type )
or die "'$phone_type' is not valid\n";
}
fun('HOME'); # valid
fun('WORK'); # valid
fun('DOG'); # run-time or compile time error
__END__
C:\Temp> dfg
'DOG' is not valid
答案 1 :(得分:3)
我建议您使用Readonly(如引用的问题所示)而不是常量。我建议采用两种可能的方法(取决于你使用的是Perl 5.10还是5.8)。
最初,相同的代码:
use strict;
use warnings;
use Readonly;
Readonly my @phone_types = qw/HOME WORK/;
Perl 5.10:
sub fun
{
my $type = shift;
die "Invalid phone type: $type" unless $type ~~ @phone_types;
# ...
}
Perl 5.8:
sub fun
{
my $type = shift;
die "Invalid phone type: $type" unless grep { $_ eq $type} @phone_types;
# ...
}
CPAN上有一个模块可以让你对参数类型和值有很大的控制权,但我不能记住它。也许其他人可以。
答案 2 :(得分:2)
package Phone::Type;
my $types;
BEGIN {
$types = {
HOME => 'Home',
WORK => 'Work',
};
}
use constant $types;
sub is_phone_type {
my ($type) = @_;
return exists $types->{$type};
}
package main;
use Carp ();
sub fun
{
my ($my_phone_type_enum) = @_;
Phone::Type::is_phone_type( $my_phone_type_enum)
or Carp::croak "Invalid type $my_phone_type_enum";
}
fun(Phone::Type->HOME); # valid
fun(Phone::Type->WORK); # valid
fun('DOG'); # run-time or compile time error
(BEGIN是在编译时设置$ types所必需的,因此它可用于use语句。)
在Perl中,对这样的事情放松是很常见的;假设函数是传递数字的数字,等等。但是如果你想进行这种验证,你可能会对Params::Validate感兴趣。