1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
2 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
4 <html xmlns="http://www.w3.org/1999/xhtml">
7 <title>Introduction to Moose</title>
8 <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
10 <meta name="generator" content="S5" />
11 <meta name="version" content="S5 1.2a2" />
12 <meta name="author" content="Eric A. Meyer" />
13 <meta name="company" content="Complex Spiral Consulting" />
14 <!-- configuration parameters -->
15 <meta name="defaultView" content="slideshow" />
16 <meta name="controlVis" content="hidden" />
17 <!-- style sheet links -->
18 <link rel="stylesheet" href="ui/default/slides.css" type="text/css" media="projection" id="slideProj" />
19 <link rel="stylesheet" href="ui/default/outline.css" type="text/css" media="screen" id="outlineStyle" />
20 <link rel="stylesheet" href="ui/default/print.css" type="text/css" media="print" id="slidePrint" />
21 <link rel="stylesheet" href="ui/default/opera.css" type="text/css" media="projection" id="operaFix" />
22 <!-- embedded styles -->
23 <style type="text/css" media="all">
24 .imgcon {width: 525px; margin: 0 auto; padding: 0; text-align: center;}
25 #anim {width: 270px; height: 320px; position: relative; margin-top: 0.5em;}
26 #anim img {position: absolute; top: 42px; left: 24px;}
27 img#me01 {top: 0; left: 0;}
28 img#me02 {left: 23px;}
30 img#me05 {top: 43px;left: 36px;}
33 <script src="ui/default/slides.js" type="text/javascript"></script>
34 <link rel="stylesheet" href="ui/custom.css" type="text/css" />
39 <div id="controls"><!-- DO NOT EDIT --></div>
40 <div id="currentSlide"><!-- DO NOT EDIT --></div>
41 <div id="header"></div>
44 <a rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/us/"><img alt="Creative Commons License" style="border-width:0" src="http://i.creativecommons.org/l/by-sa/3.0/us/88x31.png" /></a>
45 <br /><span xmlns:dc="http://purl.org/dc/elements/1.1/" href="http://purl.org/dc/dcmitype/Text" property="dc:title" rel="dc:type">Intro to Moose Class</span> by <span xmlns:cc="http://creativecommons.org/ns#" property="cc:attributionName">David Rolsky</span> is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/us/">Creative Commons Attribution-Share Alike 3.0 United States License</a>.
48 <h2>Introduction to Moose</h2>
52 <div class="presentation">
55 <h1>Introduction to Moose</h1>
60 <h1>Moose Summed Up</h1>
63 <li><strong>Declarative</strong> OO sugar</li>
64 <li>Introspectable</li>
70 <h1>Moose Background</h1>
73 <li>Created by Stevan Little, first released in 2006</li>
74 <li>Moose builds on Perl 5's native OO</li>
75 <li>Borrows ideas from other languages, notably Perl 6</li>
76 <li>Provides semantics for common operations</li>
80 <div class="slide fake-slide0">
81 <h1>Part 0: Moose Concepts</h1>
94 <li>Method modifiers</li>
95 <li>Constructor and destructor</li>
96 <li>One metaclass object</li>
99 <li>Classes do roles</li>
104 <h1>Class Example</h1>
106 <pre><code>package Person;
107 <span class="highlight">use Moose;</span></code></pre>
110 <li>Poof, a Moose-based class!</li>
118 <li>Aka property, slot, field, member variable</li>
119 <li>A piece of data owned by an object</li>
130 <li>Access-control (read-only vs read-write)</li>
131 <li>An optional type</li>
132 <li>Accessor methods</li>
133 <li>Delegation methods</li>
134 <li>Optional default value</li>
135 <li>Many more features</li>
138 <li>Stored in the object, but don't worry about that</li>
143 <h1>Attribute Example</h1>
145 <pre><code>package Person;
148 <span class="highlight">has first_name => ( is => 'rw' );</span></code></pre>
156 <li>Nothing fancy here, just Perl subroutines</li>
159 <pre><code>package Person;
162 <span class="highlight">sub greet { ... }</span></code></pre>
169 <li>Classes <strong>do</strong> (or consume) roles</li>
170 <li>Similar to mixins and Java interfaces</li>
178 <li>Like classes, can have attributes, methods, do roles</li>
179 <li>Roles can require methods</li>
180 <li>Roles are composed (flattened) into classes</li>
185 <h1>Role Example</h1>
187 <pre><code>package HasPermissions;
188 <span class="highlight">use Moose::Role;</span>
190 has is_admin => ( is => 'rw' );</code></pre>
194 <h1>Role Example</h1>
200 <pre><code>package Person;
203 <span class="highlight">with 'HasPermissions';</span></code></pre>
207 <h1>Method Modifiers</h1>
211 <li>"<strong>Before</strong> foo(), do this first"</li>
212 <li>"Do this <strong>after</strong> foo()</li>
213 <li>"Put this code <strong>around</strong> foo()"</li>
218 <h1>Before & After</h1>
220 <pre><code>before 'foo'
221 => sub { warn 'About to call foo()' };
224 => sub { warn 'Leaving foo()' };</code></pre>
231 <pre><code>around 'foo' => sub {
232 my $real_foo = shift;
235 warn 'Just before foo()';
237 $self->$real_foo( @_, bar => 42 );
239 return ( @return, 'modify return values' );
244 <h1>Type Constraints</h1>
247 <li>NOT A FULL-BLOWN TYPE SYSTEM!</li>
248 <li>But still darn useful</li>
249 <li>Constrain attribute values</li>
250 <li>Coerce from other types</li>
255 <h1>Type Constraint Example</h1>
257 <pre><code>package Person;
262 <span class="highlight">isa => 'Int'</span>,
266 Person->new( weight => 'fat' );</code></pre>
273 <li>Attributes can define delegations</li>
274 <li>Lets you hide some implementation details</li>
275 <li>Fewer objects to chase around</li>
282 <pre><code>package Person;
288 <span class="highlight">handles => { 'blog_hostname' => 'host' },</span>
291 <span class="highlight">$person->blog_hostname;</span>
292 # really calls $person->blog_uri->host</code></pre>
296 <h1>Constructors</h1>
299 <li>Moose creates <code>new()</code> for you</li>
300 <li>Provide an optional <code>BUILDARGS()</code> and <code>BUILD()</code></li>
308 <li>Provide an optional <code>DEMOLISH()</code></li>
313 <h1>Moose Meta-API</h1>
316 <li>Answers questions like ...
318 <li>What methods does this class have?</li>
319 <li>What are its parents?</li>
320 <li>What attributes does it have (including inherited attributes)?</li>
321 <li>What roles does it do?</li>
322 <li>Much, much, more</li>
329 <h1>Moose Meta-API</h1>
332 <li>Not just for introspection ...
334 <li>Add methods, attributes, roles, etc</li>
335 <li>Extend and alter core features</li>
345 <li>A quick bit of propoganda ...</li>
352 <pre><code>package Person;
355 has last_name => (
362 <h1>Without Moose</h1>
364 <pre class="small"><code>package Person;
374 if (exists $args{last_name}) {
375 confess "Attribute (last_name) does not pass the type constraint because: "
376 . "Validation failed for 'Str' with value $args{last_name}"
377 if ref($args{last_name});
378 $self->{last_nane} = $args{last_name};
381 return bless $self, $class;
389 confess "Attribute (last_name) does not pass the type constraint because: "
390 . "Validation failed for 'Str' with value $value"
392 $self->{last_name} = $value;
395 return $self->{last_name};
401 <h1>Side by side</h1>
403 <table class="side-by-side">
406 <pre><code>package Person;
409 has last_name => (
415 <pre class="small"><code>package Person;
425 if (exists $args{last_name}) {
426 confess "Attribute (last_name) does not pass the type constraint because: "
427 . "Validation failed for 'Str' with value $args{last_name}"
428 if ref($args{last_name});
429 $self->{last_nane} = $args{last_name};
432 return bless $self, $class;
440 confess "Attribute (last_name) does not pass the type constraint because: "
441 . "Validation failed for 'Str' with value $value"
443 $self->{last_name} = $value;
446 return $self->{last_name};
455 <h1>Side by side</h1>
457 <table class="side-by-side">
460 <pre><code><span class="match-moose">package Person;</span>
463 has last_name => (
469 <pre class="small"><code><span class="match-unsweet">package Person;</span>
479 if (exists $args{last_name}) {
480 confess "Attribute (last_name) does not pass the type constraint because: "
481 . "Validation failed for 'Str' with value $args{last_name}"
482 if ref($args{last_name});
483 $self->{last_nane} = $args{last_name};
486 return bless $self, $class;
494 confess "Attribute (last_name) does not pass the type constraint because: "
495 . "Validation failed for 'Str' with value $value"
497 $self->{last_name} = $value;
500 return $self->{last_name};
508 <h1>Side by side</h1>
510 <table class="side-by-side">
513 <pre><code>package Person;
514 <span class="match-moose">use Moose;</span>
516 has last_name => (
522 <pre class="small"><code>package Person;
523 <span class="match-unsweet">use strict;
530 my $self = {};</span>
532 if (exists $args{last_name}) {
533 confess "Attribute (last_name) does not pass the type constraint because: "
534 . "Validation failed for 'Str' with value $args{last_name}"
535 if ref($args{last_name});
536 $self->{last_nane} = $args{last_name};
539 <span class="match-unsweet">return bless $self, $class;
547 confess "Attribute (last_name) does not pass the type constraint because: "
548 . "Validation failed for 'Str' with value $value"
550 $self->{last_name} = $value;
553 return $self->{last_name};
561 <h1>Side by side</h1>
563 <table class="side-by-side">
566 <pre><code>package Person;
569 <span class="match-moose">has last_name => (</span>
572 <span class="match-moose">);</span></code></pre>
575 <pre class="small"><code>package Person;
585 <span class="match-unsweet">if (exists $args{last_name}) {</span>
586 confess "Attribute (last_name) does not pass the type constraint because: "
587 . "Validation failed for 'Str' with value $args{last_name}"
588 if ref($args{last_name});
589 <span class="match-unsweet">$self->{last_nane} = $args{last_name};
592 return bless $self, $class;
600 confess "Attribute (last_name) does not pass the type constraint because: "
601 . "Validation failed for 'Str' with value $value"
603 $self->{last_name} = $value;
606 return $self->{last_name};
614 <h1>Side by side</h1>
616 <table class="side-by-side">
619 <pre><code>package Person;
622 has last_name => (
623 <span class="match-moose">is => 'rw',</span>
628 <pre class="small"><code>package Person;
638 if (exists $args{last_name}) {
639 confess "Attribute (last_name) does not pass the type constraint because: "
640 . "Validation failed for 'Str' with value $args{last_name}"
641 if ref($args{last_name});
642 $self->{last_nane} = $args{last_name};
645 return bless $self, $class;
648 <span class="match-unsweet">sub last_name {
652 my $value = shift;</span>
653 confess "Attribute (last_name) does not pass the type constraint because: "
654 . "Validation failed for 'Str' with value $value"
656 <span class="match-unsweet">$self->{last_name} = $value;
659 return $self->{last_name};
660 }</span></code></pre>
667 <h1>Side by side</h1>
669 <table class="side-by-side">
672 <pre><code>package Person;
675 has last_name => (
677 <span class="match-moose">isa => 'Str',</span>
681 <pre class="small"><code>package Person;
691 if (exists $args{last_name}) {
692 <span class="match-unsweet">confess "Attribute (last_name) does not pass the type constraint because: "
693 . "Validation failed for 'Str' with value $args{last_name}"
694 if ref($args{last_name});</span>
695 $self->{last_nane} = $args{last_name};
698 return bless $self, $class;
706 <span class="match-unsweet">confess "Attribute (last_name) does not pass the type constraint because: "
707 . "Validation failed for 'Str' with value $value"
708 if ref($value);</span>
709 $self->{last_name} = $value;
712 return $self->{last_name};
720 <h1>Side by side</h1>
722 <table class="side-by-side">
723 <tr class="incremental">
727 <tr class="incremental">
728 <td>92 characters</td>
729 <td>741 characters</td>
733 <pre><code>package Person;
736 has last_name => (
742 <pre class="small"><code>package Person;
752 if (exists $args{last_name}) {
753 confess "Attribute (last_name) does not pass the type constraint because: "
754 . "Validation failed for 'Str' with value $args{last_name}"
755 if ref($args{last_name});
756 $self->{last_nane} = $args{last_name};
759 return bless $self, $class;
767 confess "Attribute (last_name) does not pass the type constraint because: "
768 . "Validation failed for 'Str' with value $value"
770 $self->{last_name} = $value;
773 return $self->{last_name};
783 <pre class="small"><code>sub new {
788 if (exists $args{last_name}) {
789 confess "Attribute (last_name) does not pass the type constraint because: "
790 . "Validation failed for 'Str' with value $args{last_name}"
791 if ref($args{last_name});
792 $self->{last_nane} = $args{last_name};
795 return bless $self, $class;
802 <pre class="small"><code>if (exists $args{last_name}) {
803 confess "Attribute (last_name) does not pass the type constraint because: "
804 . "Validation failed for 'Str' with value $args{last_name}"
805 if ref($args{last_name});
806 $self->{last_nane} = $args{last_name};
813 <code>$self->{last_nane} = $args{last_name};</code>
818 <code>$self->{last_na<span class="highlight">n</span>e}</code>
824 <pre><code>package Person;
827 has last_name => (
833 <div class="slide fake-slide0">
834 <h1>Part 1: Moose Classes</h1>
838 <h1>Moose Classes</h1>
841 <li>Moose classes are Perl packages which <code>use Moose</code></li>
846 <h1>Moose.pm and Your Class</h1>
848 <pre><code>package Person;
849 use Moose;</code></pre>
852 <li><code>Moose.pm</code> provides declarative sugar</li>
853 <li>Turns on <code>strict</code> and <code>warnings</code></li>
854 <li>Creates metaclasses for your class: <code>Person->meta</code></li>
855 <li>Moose classes automatically inherit from <code>Moose::Object</code></li>
860 <h1>What <code>Moose::Object</code> Provides</h1>
863 <li>Constructor - <code>new()</code></li>
864 <li>Calls your <code>BUILDARGS()</code> and/or <code>BUILD()</code></li>
865 <li>Calls your <code>DEMOLISH</code> during object destruction</li>
873 <li><code>extends</code> is sugar for declaring parent classes</li>
876 <pre><code>package Employee;
878 <span class="highlight">extends 'Person';</span></code></pre>
885 <li>Each call to <code>extends</code> <strong>resets</strong> your parents</li>
888 <h2 class="wrong">WRONG</h2>
890 <pre><code>package EvilEmployee;
893 extends 'Thief';</code></pre>
895 <h2 class="right">RIGHT</h2>
897 <pre><code>package EvilEmployee;
899 extends 'Person', 'Thief';</code></pre>
903 <h1>Extending un-Moose-y Parents</h1>
905 <pre><code>package My::LWP;
907 extends 'LWP';</code></pre>
910 <li>No <code>Moose::Object</code>, so ...
912 <li>No attribute-handling <code>new()</code></li>
913 <li>No <code>BUILDARGS()</code> or <code>BUILD()</code></li>
914 <li>No <code>DEMOLISH()</code></li>
917 <li>But see <code>MooseX::NonMoose</code> for a workaround</li>
922 <h1><code>overrides</code> and <code>super</code></h1>
925 <li><code>overrides</code> is another method modifier</li>
926 <li>An alternative to Perl's <code>SUPER::</code></li>
931 <h1><code>overrides</code> and <code>super</code></h1>
933 <pre><code>package Employee;
936 <span class="current">extends 'Person';</span>
938 <span class="incremental">overrides</span> work => sub {
941 die "Pay me first" unless $self->got_paid;
942 <span class="incremental">super();</span>
943 }<span class="incremental">;</span></code></pre>
947 <h1>Caveat <code>super</code></h1>
950 <li>Mostly like <code>$self->SUPER::work(@_)</code></li>
951 <li><strong>But</strong> cannot change <code>@_</code>!</li>
952 <li>Binds the parent's method at compile time</li>
957 <h1>Attributes (Part 1)</h1>
960 <li><code>has 'foo'</code></li>
961 <li>Use <code>is => 'ro'</code> or <code>is => 'rw'</code></li>
962 <li>Attributes without "is" have no accessors</li>
967 <h1>Read-write attributes</h1>
969 <pre><code>package Person;
972 has first_name => ( <span class="highlight">is => 'rw'</span> );
975 Person->new( first_name => 'Dave' );
977 $person->first_name('Stevan');
978 print $person->first_name; # Stevan</code></pre>
983 <h1>Read-only attributes</h1>
985 <pre><code>package Person;
988 has first_name => ( <span class="highlight">is => 'ro'</span> );
991 Person->new( first_name => 'Dave' );
993 $person->first_name('Stevan');
994 print $person->first_name; # Dave</code></pre>
999 <h1>There is More to Come</h1>
1002 <li>Attributes have a <em>lot</em> of features</li>
1007 <h1>Cleaning Up Moose Droppings</h1>
1009 <pre><code>package Person;
1013 Person->can('extends');</code></pre>
1016 <li>Not very hygienic</li>
1021 <h1>Cleaning Up Moose Droppings</h1>
1023 <pre><code>package Person;
1031 Person->can('extends');</code></pre>
1038 <li><code>no Moose</code> at the end of a package is a best practice</li>
1044 <h1>Immutability</h1>
1047 <li><span style="font-family: URW Chancery L; font-size: 140%">Stevan's Incantation of Fleet-Footedness</span></li>
1050 <pre><code>package Person;
1053 <span class="highlight">__PACKAGE__->meta->make_immutable;</span></code></pre>
1057 <h1>What <code>make_immutable</code> does</h1>
1061 <li>Uses <code>eval</code> to "inline" a constructor</li>
1062 <li>Memoizes a lot of meta-information</li>
1063 <li>Makes loading your class slower</li>
1064 <li>Makes object creation <em>much</em> faster</li>
1069 <h1>When to Immutabilize?</h1>
1072 <li><em>Almost</em> always</li>
1073 <li>Startup time vs execution time</li>
1078 <h1>Classes Summary</h1>
1081 <li><code>use Moose</code></li>
1082 <li><code>Class->meta</code></li>
1083 <li><code>Moose::Object</code> base class</li>
1084 <li><code>extends</code>, <code>overrides</code>, and <code>super</code></li>
1085 <li>Simple attributes: <code>has</code>, <code>is => 'ro'</code>, & <code>is => 'rw'</code></li>
1086 <li><code>no Moose</code></li>
1087 <li><code>__PACKAGE__->meta->make_immutable</code></li>
1095 $ perl bin/prove -lv t/00-prereq.t
1097 Missing anything? Install it. (see tarballs/)
1099 # perl bin/prove -lv t/01-classes.t
1101 Iterate til this passes all its tests</pre>
1104 <div class="slide fake-slide0">
1105 <h1>Part 2: Roles</h1>
1109 <h1>Just What Is a Role?</h1>
1112 <li>Mixin? Interface? Trait?</li>
1113 <li>Yes ... and more!</li>
1118 <h1>Roles Can Have State <strong>and</strong> Behavior</h1>
1120 <pre><code>package HasPermissions;
1123 <span class="current"># state
1124 has access_level => ( is => 'rw' );</span>
1126 <span class="incremental"># behavior
1129 my $required = shift;
1131 return $self->access_level >= $required;
1132 }</span></code></pre>
1137 <h1>Roles Can Define Interfaces</h1>
1139 <pre><code>package Printable;
1142 requires 'as_string';</code></pre>
1146 <h1>Roles Can Do All Three</h1>
1148 <pre><code>package Printable;
1151 requires 'as_string';
1153 has has_been_printed => ( is => 'rw' );
1157 print $self->as_string;
1158 $self->has_been_printed(1);
1163 <h1>Classes Consume Roles</h1>
1165 <pre><code>package Person;
1168 with 'HasPermissions';</code></pre>
1172 <h1>Classes Consume Roles</h1>
1174 <pre><code>my $person = Person->new(
1175 first_name => 'Kenichi',
1176 last_name => 'Asai',
1177 access_level => 42,
1180 print $person->full_name
1182 . $person->can_access(42)
1184 : 'little power';</code></pre>
1188 <h1>Roles in Practice</h1>
1191 <li>Consuming a role =~ inlining the role</li>
1196 <h1>In Other Words ...</h1>
1198 <pre><code>package Person;
1201 <span class="highlight">with 'Printable';</span></code></pre>
1205 <h1>In Other Words ...</h1>
1207 <pre><code>package Person;
1210 <span class="delete">with 'Printable';</span>
1212 <span class="highlight">has has_been_printed => ( is => 'rw' );
1216 print $self->as_string;
1217 $self->has_been_printed(1);
1218 }</span></code></pre>
1225 <li>Role consumption is introspectable</li>
1228 <pre><code>if ( Person->does('Printable') ) { ... }
1232 if ( Person->meta->does('Printable') ) { ... }</code></pre>
1237 <h1>These Names Are the Same</h1>
1240 <li>What if a role and class define the same method?</li>
1241 <li>A class's <em>local</em> methods win over the role's</li>
1242 <li>The role's methods win over the class's <em>inherited</em> methods</li>
1247 <h1>Conflicts Between Roles</h1>
1250 <li>Two roles with a method of the same name</li>
1251 <li>Generates a compile-time error when consumed by a class</li>
1256 <h1>Conflict Example</h1>
1258 <pre><code>package IsFragile;
1263 package CanBreakdance;
1266 sub break { ... }</code></pre>
1270 <h1>Conflict Example</h1>
1272 <pre><code>package FragileDancer;
1275 <span class="highlight">with 'IsFragile', 'CanBreakdance';</span></code></pre>
1278 <li>Only one <code>with</code>!</li>
1283 <h1>Conflict Resolution</h1>
1286 <li>The consuming class must resolve the conflict by implementing th emethod</li>
1287 <li>Can use some combination of method exclusion and aliasing</li>
1292 <h1>Method Aliasing</h1>
1294 <pre><code>package FragileDancer;
1297 <span class="highlight">with 'IsFragile' =>
1299 { break => 'break_bone' } },
1302 { break => 'break_it_down' } };</span></code></pre>
1305 <li>Renames the roles' methods</li>
1306 <li>Still conflicts, need to <code>exclude</code> as well</li>
1311 <h1>Method Exclusion</h1>
1313 <pre><code>package FragileDancer;
1316 <span class="highlight">with 'IsFragile' =>
1318 { break => 'break_bone' },
1319 exclude => 'break' },
1322 { break => 'break_dance' },
1323 exclude => 'break' };</span></code></pre>
1327 <h1>And then ...</h1>
1329 <pre><code>package FragileDancer;
1336 if ( rand(1) < 0.5 ) {
1343 <h1>Still Full of Fail</h1>
1346 <li>Roles are also about semantics!</li>
1347 <li>We've fulfilled the letter and lost the spirit</li>
1348 <li>Roles have a <em>meaning</em></li>
1349 <li>Think twice before blindly aliasing and excluding methods!</li>
1354 <h1>Hot Role-on-Role Action</h1>
1356 <pre><code>package Comparable;
1359 requires 'compare';</code></pre>
1363 <h1>Hot Role-on-Role Action</h1>
1365 <pre><code>package TestsEquality;
1372 return $self->compare(@_) == 0;
1377 <h1>And then ...</h1>
1379 <pre><code>package Integer;
1382 with 'TestsEquality';
1384 # Satisfies the Comparable role
1387 Integer->does('TestsEquality'); # true
1388 Integer->does('Comparable'); # also true!</code></pre>
1392 <h1>Name Conflicts Between Roles</h1>
1394 <pre><code>package HasSubProcess;
1397 <span class="highlight">sub execute { ... }</span>
1402 with 'HasSubProcess';
1404 <span class="highlight">sub execute { ... }</span></code></pre>
1408 <h1>Delayed Conflict</h1>
1410 <pre><code>package StateOfTexas;
1411 with 'Killer';</code></pre>
1414 <li><code>StateOfTexas</code> must implement its own <code>execute</code></li>
1415 <li>But loading the <code>Killer</code> role by itself does not cause an error</li>
1420 <h1>Roles as Interfaces</h1>
1423 <li>Roles can <code>require</code> methods of their consumers</li>
1424 <li>Compile-time checks</li>
1425 <li>Method must exist when the role is consumed</li>
1430 <h1>The Attribute Gotcha</h1>
1432 <pre><code>package HasSize;
1435 <span class="current">requires 'size';</span>
1440 <span class="incremental">with 'HasSize';
1442 has size => ( is => 'ro' );</span></code></pre>
1446 <h1>The Attribute Gotcha Workaround</h1>
1448 <pre><code>package HasSize;
1456 has size => ( is => 'ro' );
1458 with 'HasSize';</code></pre>
1462 <h1>Compile-time Is a Lie</h1>
1465 <li>Really, it's <em>package load</em> time</li>
1466 <li>That's run-time, but before the "real" run-time</li>
1467 <li>Moose does not rewire Perl, it's just sugar!</li>
1468 <li>(but <code>MooseX::Declare</code> <em>does</em> rewire Perl)</li>
1473 <h1>Enforcing Roles</h1>
1475 <pre><code>package Comparison;
1478 has [ 'left', 'right' ] => (
1480 <span class="highlight">does => 'Comparable',</span>
1485 <li>A sneak peek at type constraints</li>
1491 <h1>Roles Can Be Applied to Objects</h1>
1493 <pre><code>use Moose::Util qw( apply_all_roles );
1495 my $fragile_person = Person->new( ... );
1496 apply_all_roles( $fragile_person, 'IsFragile' );</code></pre>
1499 <li>Does not change the <code>Person</code> class</li>
1500 <li>Works with non-Moose classes, great for monkey-patching!</li>
1505 <h1>Roles Are Dirty Too</h1>
1508 <li>Once again, clean up those Moose droppings</li>
1511 <pre><code>package Comparable;
1516 <span class="highlight">no Moose::Role;</span></code></pre>
1519 <li>But roles cannot be made immutable</li>
1524 <h1>The Zen of Roles</h1>
1527 <li>Roles represent discrete units of ...
1534 <li>Roles are shareable between unrelated classes</li>
1535 <li>Roles are what a class <em>does</em>, not what it <em>is</em></li>
1536 <li>Roles <em>add</em> functionality, inheritance <em>specializes</em></li>
1541 <h1>Abstract Examples</h1>
1544 <li>Human <em>@ISA</em> Animal</li>
1545 <li>Human <em>does</em> Toolmaker (as <em>does</em> Chimpanzee)</li>
1546 <li>Car <em>@ISA</em> Vehicle</li>
1547 <li>Car <em>does</em> HasEngine</li>
1552 <h1>Real Examples</h1>
1555 <li>Objects representing SQL database components and queries
1557 <li>Schema, Table, Column, ColumnAlias</li>
1558 <li>Select, Insert, Update, Delete</li>
1565 <h1>Real Examples</h1>
1568 <li>Column and ColumnAlias both <em>do</em> ColumnLike</li>
1569 <li>ColumnLike things can be used in certain parts of queries</li>
1570 <li>All queries <em>do</em> HasWhereClause</li>
1571 <li>Select <em>does</em> Comparable and Selectable (for subselects)</li>
1572 <li>A where clause requires its components to <em>do</em> Comparable</li>
1580 # perl bin/prove -lv t/02-roles.t
1582 Iterate til this passes all its tests</pre>
1591 Copyright 2009 David Rolsky. All Rights Reserved.
1593 This work is licensed under a Creative Commons Attribution-Share Alike
1594 3.0 United States License See
1595 http://creativecommons.org/licenses/by-sa/3.0/us/ for details.