字段 - 编译时类字段
{
package Foo;
use fields qw(foo bar _Foo_private);
sub new {
my Foo $self = shift;
unless (ref $self) {
$self = fields::new($self);
$self->{_Foo_private} = "this is Foo's secret";
}
$self->{foo} = 10;
$self->{bar} = 20;
return $self;
}
}
my $var = Foo->new;
$var->{foo} = 42;
# this will generate a run-time error
$var->{zap} = 42;
# this will generate a compile-time error
my Foo $foo = Foo->new;
$foo->{zap} = 24;
# subclassing
{
package Bar;
use base 'Foo';
use fields qw(baz _Bar_private); # not shared with Foo
sub new {
my $class = shift;
my $self = fields::new($class);
$self->SUPER::new(); # init base fields
$self->{baz} = 10; # init own fields
$self->{_Bar_private} = "this is Bar's secret";
return $self;
}
}
fields
编译指示支持编译时和运行时验证的类字段。
注意:当前实现将声明的字段保存在调用包的 %FIELDS 哈希中,但这在将来的版本中可能会改变。不要直接更新 %FIELDS 哈希,因为它必须在编译时创建才能完全发挥作用,就像此编译指示所做的那样。
如果使用包含引用的类型化词法变量(my Class $var
)来访问哈希元素,并且类型名称相同的包使用此编译指示声明了类字段,那么哈希键将在编译时进行验证。如果变量没有类型化,则访问仅在运行时检查。
相关的 base
编译指示将组合来自基类的字段和使用 fields
编译指示声明的任何字段。这使得字段继承能够正常工作。继承的字段可以被覆盖,但如果启用了警告,则会生成警告。
仅适用于 Perl 5.8.x 及更早版本:以下划线开头的字段名称对类而言是私有的,子类无法访问。
此外,在 Perl 5.8.x 及更早版本中,此 pragma 使用伪哈希,其效果是您可以拥有具有命名字段的对象,这些对象与数组一样紧凑且快速访问,只要通过正确类型的变量访问这些对象即可。
支持以下函数
fields::new() 创建并祝福一个哈希,该哈希包含使用 fields
pragma 在指定类中声明的字段。这是构建基于字段的对象的推荐方法。
这使得编写这样的构造函数成为可能
package Critter::Sounds;
use fields qw(cat dog bird);
sub new {
my $self = shift;
$self = fields::new($self) unless ref $self;
$self->{cat} = 'meow'; # scalar element
@$self{'dog','bird'} = ('bark','tweet'); # slice
return $self;
}
此函数仅在 Perl 5.8.x 及更早版本中有效。从 Perl 5.10 开始,伪哈希已被移除。请考虑使用受限哈希或 fields::new() 代替(在 5.10+ 下本身使用受限哈希)。参见 Hash::Util。在 5.10 或更高版本下使用 fields::phash() 会导致错误。
fields::phash() 可用于创建和初始化一个普通的(未祝福的)伪哈希。此函数应始终用于创建伪哈希,而不是直接创建。
如果第一个参数是对数组的引用,则伪哈希将使用该数组中的键创建。如果提供了第二个参数,它也必须是对数组的引用,其元素将用作值。如果第二个数组包含的元素少于第一个数组,则伪哈希的尾部元素将不会被初始化。这使得它特别适合于从子例程参数创建伪哈希。
sub dogtag {
my $tag = fields::phash([qw(name rank ser_num)], [@_]);
}
fields::phash() 还接受一个键值对列表,这些键值对将用于构建伪哈希。示例
my $tag = fields::phash(name => "Joe",
rank => "captain",
ser_num => 42);
my $pseudohash = fields::phash(%args);