NAME
Object::Pad::FieldAttr::Checked - apply value constraint checks to
Object::Pad fields
SYNOPSIS
With Data::Checks:
use Object::Pad;
use Object::Pad::FieldAttr::Checked;
use Data::Checks qw( Num );
class Point {
field $x :param :reader :Checked(Num);
field $y :param :reader :Checked(Num);
}
Point->new( x => 123, y => "456" ); # this is fine
Point->new( x => "hello", y => "world" ); # throws an exception
DESCRIPTION
This module provides a third-party field attribute for
Object::Pad-based classes, which declares that values assigned to the
field must conform to a given constraint check.
WARNING The ability for Object::Pad to take third-party field
attributes is still new and highly experimental, and subject to much
API change in future. As a result, this module should be considered
equally experimental.
Additionally, the behaviour provided by this module should be
considered more of a work-in-progress stepping stone. Ideally,
constraint syntax ought to be provided in a much more fundamental way
by Perl itself, allowing it to be used on my lexicals, subroutine
parameters, and other places as well as object fields. This module is
more of a placeholder to allow some part of that behaviour to be
specified for object fields, while not getting in the way of a more
general, more powerful system being added in future.
FIELD ATTRIBUTES
:Checked
field $name :Checked(EXPRESSION) ...;
Declares that any value assigned to the field during the constructor or
using an accessor method must conform to the constraint checker
specified by the expression. Attempts to assign a non-conforming value
will throw an exception and the field will not be modified. Currently
only scalar fields are supported.
At compiletime, the string given by EXPRESSION is eval()'ed in scalar
context, and its result is stored as part of the field's definition.
The expression must yield a value usable by Data::Checks. Namely, one
of:
* Any of the constraint checkers provided by the Data::Checks module
itself.
* An object reference with a check method:
$ok = $checkerobj->check( $value );
* A code reference:
$ok = $checkersub->( $value );
* A plain string giving the name of a package with a check method:
$ok = $checkerpkg->check( $value );
If using a plain package name as a checker, be sure to quote package
names so it will not upset use strict.
field $x :Checked('CheckerPackage');
As this is the interface supported by Types::Standard, any constraint
object provided by that module is already supported here.
use Types::Standard qw( Str Num );
field $name :Checked(Str);
field $age :Checked(Num);
At runtime, this constraint checker is used every time an attempt is
made to assign a value to the field from outside the object class,
whether that is from :param initialisation, or invoking a :writer,
:accessor or :mutator. The checker is used as the invocant for invoking
a check method, and the new value for the field is passed as an
argument. If the method returns true, the assignment is allowed. If
false, it is rejected with an exception and the field itself remains
unmodified.
(For performance reasons, the check method is actually resolved into a
function at compiletime when the :Checked attribute is applied, and
this stored function is the one that is called at assignment time. If
the method itself is replaced later by globref assignment or other
trickery, this updated function will not be used.)
Note carefully that direct assignment into the field variable by code
within the class is not checked. This is partly because of design
considerations, and partly because any way to implement that would be
horribly slow, or flat-out impossible. Prior to version 0.04 this
module used to claim that even direct assignments would be checked. but
this gave a false sense of safety if deeply-nested containers were
involved and modified from within.
SEE ALSO
* Object::Pad::FieldAttr::Isa - apply class type constraints to
Object::Pad fields
AUTHOR
Paul Evans <leonerd@leonerd.org.uk>