【问题标题】:Perl Moose attributes with minimum, maximum, and default value具有最小值、最大值和默认值的 Perl Moose 属性
【发布时间】:2013-05-27 19:29:06
【问题描述】:

使用 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);

是否可以在一个属性中同时包含所有四个(当前、默认、最小值、最大值)?

【问题讨论】:

    标签: perl attributes moose


    【解决方案1】:

    我想你想创建一个验证规则。

    use Moose::Util::TypeConstraints;
    
    subtype 'ScaleVal',
       as 'Int',
       where { 100 <= $_ && $_ <= 1000 };
    
    has attr => (
       is      => 'rw',
       isa     => 'ScaleVal',
       default => 300,
    );
    

    【讨论】:

    • 这看起来不错。有什么方法可以检查属性吗?例如。从中获取最小值、最大值和默认值?
    • AFAIK 不适用于 Moose::Meta::TypeConstraint。您可以创建一个包类来封装此功能,而不是创建一个子类型,并使用 min,max 属性包装一个子类型。
    • @ikegami 请告诉我,我在哪里可以阅读有关 Moose 类系统的信息?
    • @loldop,Moose 发行版附带的 Moose::Manual::* 和 Moose::Cookbook::* 文件?
    【解决方案2】:

    当然,有很多方法可以将一堆值组合成一个更复杂的值——这基本上就是数据结构研究的内容。选择什么特定的数据结构是一个相当复杂的问题,很大程度上取决于您的实际用例。

    我对您的情况知之甚少,但我从您的问题中了解到,所有这些属性都代表结构相似的概念。所以我会创建一个新的数据类型,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 来描述以下属性具有最小和最大合法值。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-01
      相关资源
      最近更新 更多