forked from szabgab/perlmaven.com
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathattribute-types-in-perl-classes-when-using-moose.tt
More file actions
122 lines (90 loc) · 3.48 KB
/
attribute-types-in-perl-classes-when-using-moose.tt
File metadata and controls
122 lines (90 loc) · 3.48 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
=title Attribute types in Perl classes when using Moose
=timestamp 2013-02-26T06:13:10
=indexes OOP, Moose, object oriented, class, object, instance, constructor, getter, setter, accessor, attribute
=status show
=books advanced_book
=author szabgab
=index 1
=archive 1
=feed 1
=comments 1
=social 1
=abstract start
In a simple Perl script we usually don't care much about the types of the values,
but as the application grows, a type system can improve the correctness of the application.
Moose lets you define a type for each attribute and then enforces the types via the setters.
=abstract end
After the the first
<a href="/object-oriented-perl-using-moose">introduction to Object Oriented Perl with Moose</a>,
you should probaly get familiar with the type-checking system of Moose.
<h2>Set the type to be Int</h2>
This is our first sample script:
<code lang="perl">
use strict;
use warnings;
use v5.10;
use Person;
my $student = Person->new( name => 'Joe' );
$student->year(1988);
say $student->year;
$student->year('23 years ago');
</code>
After loading the Person module (the class), we create the $student object
by calling the "new" constructor of the class.
Then we call the "year" accessor and set the value to 1998. After printing the value
we try to set it to "23 years ago".
In the module you can see two attributes. The "year" attribute has an <hl>isa</hl> entry
with a value <hl>Int</hl>. Because of this, the setter Moose creates will restrict the
values it accepts to integers.
<code lang="perl">
package Person;
use Moose;
has 'name' => (is => 'rw');
has 'year' => (isa => 'Int', is => 'rw');
1;
</code>
Save the module in "somedir/lib/Person.pm" and save the script in "somedir/bin/app.pl" then
from within the somedir directory run the script with "perl -Ilib bin/app.pl"
After printing the value 1988, we get the following error:
<code>
Attribute (year) does not pass the type constraint because:
Validation failed for 'Int' with value "23 years ago"
at accessor Person::year (defined at lib/Person.pm line 5) line 4
Person::year('Person=HASH(0x19a4120)', '23 years ago')
called at script/person.pl line 13
</code>
This error message shows that Moose did not accept the string "23 years ago" as an Integer.
<h2>Another class as a type constraint</h2>
Besides the
<a href="https://metacpan.org/module/Moose::Util::TypeConstraints#Default-Type-Constraints">default type constraints</a>,
Moose also allows you to use the name of any existing class as a type constraint.
For example you can declare that the "birthday" attribute must be a DateTime object.
<code lang="perl">
package Person;
use Moose;
has 'name' => (is => 'rw');
has 'birthday' => (isa => 'DateTime', is => 'rw');
1;
</code>
Try the example script:
<code lang="perl">
use strict;
use warnings;
use v5.10;
use Person;
use DateTime;
my $student = Person->new( name => 'Joe' );
$student->birthday( DateTime->new( year => 1988, month => 4, day => 17) );
say $student->birthday;
$student->birthday(1988);
</code>
You can see, the first call to the "birthday" setter receives a DateTime object
created on the spot. This call works well. The second call receives the number 1988
and throws an exception similar to the previous one:
<code>
Attribute (birthday) does not pass the type constraint because:
Validation failed for 'DateTime' with value 1988
at accessor Person::birthday (defined at lib/Person.pm line 5) line 4
Person::birthday('Person=HASH(0x2143928)', 1988)
called at script/person.pl line 14
</code>