Test2::Util::HashBase - 构建基于哈希的类。
一个类
package My::Class;
use strict;
use warnings;
# Generate 3 accessors
use Test2::Util::HashBase qw/foo -bar ^baz <bat >ban +boo/;
# Chance to initialize defaults
sub init {
my $self = shift; # No other args
$self->{+FOO} ||= "foo";
$self->{+BAR} ||= "bar";
$self->{+BAZ} ||= "baz";
$self->{+BAT} ||= "bat";
$self->{+BAN} ||= "ban";
$self->{+BOO} ||= "boo";
}
sub print {
print join ", " => map { $self->{$_} } FOO, BAR, BAZ, BAT, BAN, BOO;
}
对其进行子类化
package My::Subclass;
use strict;
use warnings;
# Note, you should subclass before loading HashBase.
use base 'My::Class';
use Test2::Util::HashBase qw/bub/;
sub init {
my $self = shift;
# We get the constants from the base class for free.
$self->{+FOO} ||= 'SubFoo';
$self->{+BUB} ||= 'bub';
$self->SUPER::init();
}
使用它
package main;
use strict;
use warnings;
use My::Class;
# These are all functionally identical
my $one = My::Class->new(foo => 'MyFoo', bar => 'MyBar');
my $two = My::Class->new({foo => 'MyFoo', bar => 'MyBar'});
my $three = My::Class->new(['MyFoo', 'MyBar']);
# Readers!
my $foo = $one->foo; # 'MyFoo'
my $bar = $one->bar; # 'MyBar'
my $baz = $one->baz; # Defaulted to: 'baz'
my $bat = $one->bat; # Defaulted to: 'bat'
# '>ban' means setter only, no reader
# '+boo' means no setter or reader, just the BOO constant
# Setters!
$one->set_foo('A Foo');
#'-bar' means read-only, so the setter will throw an exception (but is defined).
$one->set_bar('A bar');
# '^baz' means deprecated setter, this will warn about the setter being
# deprecated.
$one->set_baz('A Baz');
# '<bat' means no setter defined at all
# '+boo' means no setter or reader, just the BOO constant
$one->{+FOO} = 'xxx';
此包用于生成基于哈希表的类。使用此类将为您提供一个 new()
方法,以及生成您请求的访问器。生成的访问器将是 getter,还将为您生成 set_ACCESSOR
setter。您还将获得每个访问器的常量(全部大写),这些常量返回该访问器的哈希表中的键。单继承也受支持。
这是 Object::HashBase 的捆绑副本。此文件是使用 /home/exodist/perl5/perlbrew/perls/main/bin/hashbase_inc.pl
脚本生成的。
创建新实例。
如果包继承链中已存在 new()
方法,则 HashBase 不会导出 new()
。
如果您不想要此方法,可以定义自己的方法,只需在加载 Test2::Util::HashBase 之前声明即可。
package My::Package;
# predeclare new() so that HashBase does not give us one.
sub new;
use Test2::Util::HashBase qw/foo bar baz/;
# Now we define our own new method.
sub new { ... }
这样 HashBase 就会看到您有自己的 new()
方法。或者,您可以在加载 HashBase 之前定义方法,而不仅仅是声明,但这会分散您的使用语句。
创建对象最常见的方法是传入键/值对,其中每个键都是一个属性,每个值都是您要分配给该属性的内容。不会执行任何检查来验证属性或值是否有效,如果需要,您可以在 init()
中执行此操作。
如果您愿意,可以传入 hashref 而不是对。这样做时,hashref 将被复制,并且副本将被标记为对象返回。没有办法要求 HashBase 标记特定的 hashref。
在某些情况下,一个对象可能只有 1 或 2 个属性,在这种情况下,hashref 可能会过于冗长。在这些情况下,您可以传入仅包含值的 arrayref。值将按属性列出的顺序分配给属性。当涉及继承时,父类的属性将排在子类之前。
这给了您机会为字段设置一些默认值。唯一的参数是 $self
,其索引已由构造函数设置。
注意:Test2::Util::HashBase 在构造期间使用 $class->can('init')
检查 init。它不会对创建的对象调用 can()
。还要注意,检查结果已被缓存,它只会被检查一次,即首次创建您类的实例时。这意味着在首次构造之后添加 init()
方法将导致它被忽略。
要生成访问器,请在使用模块时列出它们
use Test2::Util::HashBase qw/foo/;
这将在您的名称空间中生成以下子项
Getter,用于获取 foo
字段的值。
设置器,用于设置 foo
字段的值。
常量,返回字段 foo
在类哈希引用中的键。子类也会将此函数作为常量(而不仅仅是方法)获取,这意味着它会被复制到子类名称空间中。
使用这些常量的主要原因是为了帮助避免拼写错误和类似的错别字。但如果你忘记添加前缀“+”,它将帮不了你。
use Test2::Util::HashBase qw/-foo/;
抛出一个异常,告诉你该属性是只读的。这将被导出以覆盖父类中该属性的任何活动设置器。
use Test2::Util::HashBase qw/^foo/;
这将设置值,但它也会警告你该方法已弃用。
use Test2::Util::HashBase qw/<foo/;
只提供一个读取器,根本没有定义 set_foo
方法。
use Test2::Util::HashBase qw/>foo/;
只提供一个写入器(set_foo
),根本没有定义 foo
方法。
use Test2::Util::HashBase qw/+foo/;
这不会为你创建任何方法,它只会添加 FOO
常量。
你可以对现有的 HashBase 类进行子类化。
use base 'Another::HashBase::Class';
use Test2::Util::HashBase qw/foo bar baz/;
基本类已为你添加到 @ISA
中,并且基本类中的所有常量都会自动添加到子类中。
Test2::Util::HashBase 提供了一个函数,用于检索 Test2::Util::HashBase 类的属性列表。
以上两种形式都可以使用。这将返回对对象定义的属性列表。此列表按属性定义顺序返回,父类属性在子类属性之前列出。在返回列表之前,将删除重复的属性。
注意:此列表用于 $class->new(\@ARRAY)
构造函数中,以确定每个值将与哪个属性配对。
HashBase 的源代码存储库位于 http://github.com/Test-More/HashBase/。
版权所有 2017 Chad Granum <[email protected]>。
此程序是免费软件;您可以在与 Perl 相同的条款下重新分发和/或修改它。
请参见 https://dev.perl5.cn/licenses/