使用Moose,可以创建具有默认值的属性。 我有一组属性都具有最小值,最大值和默认值。 它们是表示比例的属性(例如Tk :: Scale)。
目前,我至少有3个属性: 当前和默认值:
has 'attr' => (is => 'rw', isa => 'Int', default => 300, lazy => 1, clearer => '_clear_attr');
(分钟):
has 'attr_min' => (is => 'rw', isa => Int', default => 100);
最大:
has 'attr_max' => (is => 'rw', isa => Int', default => 1000);
是否可以在一个属性中包含所有四个(当前,默认,最小,最大)?
答案 0 :(得分:7)
我认为您要创建验证规则。
use Moose::Util::TypeConstraints;
subtype 'ScaleVal',
as 'Int',
where { 100 <= $_ && $_ <= 1000 };
has attr => (
is => 'rw',
isa => 'ScaleVal',
default => 300,
);
答案 1 :(得分:1)
当然有很多方法可以将一堆值组合成一个更复杂的值 - 这基本上就是对数据结构的研究。要选择哪些特定的数据结构是一个相当复杂的问题,高度依赖于您的实际用例。
我对你的案例知之甚少,但我从你的问题中得到的结论是,所有这些属性都代表了类似结构的概念。所以我会创建一个新的数据类型Scale
:
use MooseX::Declare;
class Scale {
for (qw/min max def/) {
has $_ => (is => 'ro', isa => 'Num', required => 1);
}
has val => (is => 'rw', isa => 'Num', lazy_build => 1);
method _build_val() {
return $self->def;
}
method BUILD($args) {
confess "Out of range!" unless $self->_is_in_range($self->val);
}
method _is_in_range($val) {
return defined $val && $val >= $self->min && $val <= $self->max;
}
before val ($new_val?) {
return unless defined $new_val;
confess "Out of range!" unless $self->_is_in_range($new_val);
}
}
我会在ThingWithScale
对象支持的某些Scale
上显示属性。
class ThingWithScale {
has _attr => (
is => 'ro', isa => 'Scale',
default => sub { shift->_make_attr() },
);
method _make_attr($class: $val?) {
return Scale->new(
min => 100, max => 1000, def => 200,
(defined $val ? (val => $val) : ()),
)
}
# Convert `attr` argument to a `Scale` object before passing to real constructor.
sub BUILDARGS {
my ($class, %args) = @_;
if (defined (my $attr = delete $args{attr})) {
%args = (
%args,
_attr => $class->_make_attr($attr)
);
}
return $class->SUPER::BUILDARGS(%args);
}
}
my $thing = ThingWithScale->new(attr => 101);
关于我编写BUILDARGS
方法从简单的构造函数参数自动实例化Scale对象的时间,我会意识到我真正想做的是创建一个新属性trait描述具有最小和最大合法值的属性。