Ответ Синана BUILD
, вероятно, является самым разумным и простым решением.Использование BUILDARGS
в качестве упомянутого Дэйва также является разумным решением.
Мне показалось, что стоит упомянуть, что можно также использовать Type Coercions.Для данного класса:
class LineSegment {
has [qw(startX startY endX endY)] => (
isa => 'Num',
is => 'ro',
required => 1
);
}
Вы можете использовать набор принуждений, например, так:
class_type 'LineSegment';
subtype StartLength
=> as Hashref
=> where { exists $_->{startX} && $_->{startY} && $_->{length} };
subtype EndLength
=> as Hashref
=> where { exists $_->{endX} && $_->{endY} && $_->{length} };
coerce LineSegment
=> from StartLength
=> via { my ($endX, $endY) = calc_end($_);
LineSegment->new(
startX => $_->{startX},
startY => $_->{startY},
endX => $endX,
endY => $endY,
)};
coerce LineSegment
=> from EndLength
=> via { my ($startX, $startY) = calc_start($_);
LineSegment->new(
startX => $startX,
startY => $startY,
endX => $_->{endX},
endY => $_->{endY},
)};
Тогда в вашем коде:
use Moose::Util::TypeConstraints;
find_type_constraint('LineSegment')->coerce({
startX => $x,
startY => $y,
length => $length
});
Хотя, возможно, избыточноВ этом примере есть несколько раз, когда принуждение является элегантным решением.Например, если у вас есть существующий класс LineSegment
, к которому вы не хотите добавлять атрибут length
(хотя BUILDARGS
также будет работать там хорошо)