7

Moose を使用すると、デフォルト値を持つ属性を作成できます。すべてに最小値、最大値、およびデフォルト値を持つ一連の属性があります。これらはスケールを表す属性です (Tk::Scale など)。

現在、少なくとも 3 つの属性があります: current と default:

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

4 つすべて (現在、デフォルト、最小、最大) を 1 つの属性に含めることは可能ですか?

4

2 に答える 2

7

検証ルールを作成したいと思います。

use Moose::Util::TypeConstraints;

subtype 'ScaleVal',
   as 'Int',
   where { 100 <= $_ && $_ <= 1000 };

has attr => (
   is      => 'rw',
   isa     => 'ScaleVal',
   default => 300,
);
于 2013-05-27T19:32:40.550 に答える
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);

単純なコンストラクター パラメーターから Scale オブジェクトを自動的にインスタンス化するメソッドを書いていた頃BUILDARGS、私が本当にやりたかったことは、有効な最小値と最大値を持つ属性を記述する新しい属性トレイトを発明することであることに気付きました。

于 2013-05-30T15:48:14.293 に答える