Sinan BUILD answer is probably the easiest, most direct solution. Using BUILDARGS , as mentioned above, is also a smart solution.
I felt it worth mentioning that Type Coercions could be used. Given the class:
class LineSegment { has [qw(startX startY endX endY)] => ( isa => 'Num', is => 'ro', required => 1 ); }
You can use a set of constraints, for example:
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}, )};
Then in your code:
use Moose::Util::TypeConstraints; find_type_constraint('LineSegment')->coerce({ startX => $x, startY => $y, length => $length });
Although this example may be redundant, there are several times when coercion is an elegant solution. For example, if you have an existing LineSegment class, you do not want to add the length attribute (although BUILDARGS will work BUILDARGS too)
source share