File Coverage

blib/lib/Mars/Kind.pm
Criterion Covered Total %
statement 146 156 93.5
branch 18 34 52.9
condition 9 24 37.5
subroutine 34 35 97.1
pod 18 19 94.7
total 225 268 83.9


line stmt bran cond sub pod time code
1             package Mars::Kind;
2              
3 8     8   1641 use 5.018;
  8         21  
4              
5 8     8   69 use strict;
  8         13  
  8         126  
6 8     8   36 use warnings;
  8         11  
  8         1168  
7              
8             # VARIABLES
9              
10             state $cache = {};
11              
12             # METHODS
13              
14             sub ARGS {
15 225     225 1 6405 my ($self, @args) = @_;
16              
17             return (!@args)
18             ? ($self->DATA)
19             : ((@args == 1 && ref($args[0]) eq 'HASH')
20 225 100 66     1294 ? (!%{$args[0]} ? $self->DATA : {%{$args[0]}})
  9 50       32  
  8 100       45  
    100          
21             : (@args % 2 ? {@args, undef} : {@args}));
22             }
23              
24             sub ATTR {
25 38     38 1 8297 my ($self, $attr, @args) = @_;
26              
27 8     8   49 no strict 'refs';
  8         23  
  8         279  
28 8     8   38 no warnings 'redefine';
  8         10  
  8         2058  
29              
30 38         59 *{"@{[$self->NAME]}::$attr"}
  38         90  
31 29     29   15353 = sub {@_ = ($_[0], $attr, @_[1 .. $#_]); goto \&attr}
  29         99  
32 38 50       368 if !$self->can($attr);
33              
34 38         57 my $index = int(keys(%{$${"@{[$self->NAME]}::META"}{ATTR}})) + 1;
  38         41  
  38         41  
  38         68  
35              
36 38         107 $${"@{[$self->NAME]}::META"}{ATTR}{$attr} = [$index, [$attr, @args]];
  38         65  
  38         69  
37              
38 38         138 return $self;
39             }
40              
41             sub AUDIT {
42 15     15 1 38 my ($self) = @_;
43              
44 15         20 return $self;
45             }
46              
47             sub BASE {
48 16     16 1 4882 my ($self, $base, @args) = @_;
49              
50 8     8   52 no strict 'refs';
  8         14  
  8         3778  
51              
52 16 50 66     30 if (!keys(%{"${base}::"}) && !${"${base}::META"} && !$$cache{$base}++) {
  16   33     68  
  1         8  
53 1 50       2 local $@; eval "require $base"; die $@ if $@;
  1         63  
  1         12  
54             }
55              
56 15         27 @{"@{[$self->NAME]}::ISA"} = (
  15         28  
57 15         28 $base, (grep +($_ ne $base), @{"@{[$self->NAME]}::ISA"})
  15         22  
  15         45  
58             );
59              
60 15         60 my $index = int(keys(%{$${"@{[$self->NAME]}::META"}{BASE}})) + 1;
  15         26  
  15         22  
  15         57  
61              
62 15         38 $${"@{[$self->NAME]}::META"}{BASE}{$base} = [$index, [$base, @args]];
  15         19  
  15         37  
63              
64 15         73 return $self;
65             }
66              
67             sub BLESS {
68 222     222 1 21296 my ($self, @args) = @_;
69              
70 222         548 my $data = $self->DATA($self->ARGS($self->BUILDARGS(@args)));
71 222         576 my $anew = bless($data, $self->NAME);
72              
73 222         615 $anew->BUILD($data);
74              
75 222         1292 return $anew;
76             }
77              
78             sub BUILD {
79 168     168 1 229 my ($self) = @_;
80              
81 168         193 return $self;
82             }
83              
84             sub BUILDARGS {
85 214     214 1 327 my ($self, @args) = @_;
86              
87 214         501 return (@args);
88             }
89              
90             sub DATA {
91 241     241 1 412 my ($self, $data) = @_;
92              
93 241 100       777 return $data ? {%$data} : {};
94             }
95              
96             sub DESTROY {
97 171     171   13608 my ($self) = @_;
98              
99 171         721 return;
100             }
101              
102             sub DOES {
103 42     42 1 1517 my ($self, $role) = @_;
104              
105 42 50       101 return if !$role;
106              
107 42         116 return $self->META->role($role);
108             }
109              
110             sub EXPORT {
111 0     0 1 0 my ($self, $into) = @_;
112              
113 0         0 return [];
114             }
115              
116             sub FROM {
117 5     5 1 3482 my ($self, $base) = @_;
118              
119 5         26 $self->BASE($base);
120              
121 5 50       39 $base->AUDIT($self->NAME) if $base->can('AUDIT');
122              
123 5         62 return $self;
124             }
125              
126             sub IMPORT {
127 13     13 1 53 my ($self, $into) = @_;
128              
129 13         45 return $self;
130             }
131              
132             sub META {
133 151     151 1 2595 my ($self) = @_;
134              
135 8     8   50 no strict 'refs';
  8         18  
  8         578  
136              
137 151         4525 require Mars::Meta;
138              
139 151         340 return Mars::Meta->new(name => $self->NAME);
140             }
141              
142             sub MIXIN {
143 10     10 0 6129 my ($self, $mixin, @args) = @_;
144              
145 8     8   45 no strict 'refs';
  8         16  
  8         665  
146              
147 10 0 33     20 if (!keys(%{"${mixin}::"}) && !${"${mixin}::META"} && !$$cache{$mixin}++) {
  10   0     43  
  0         0  
148 0 0       0 local $@; eval "require $mixin"; die $@ if $@;
  0         0  
  0         0  
149             }
150              
151 8     8   44 no warnings 'redefine';
  8         60  
  8         339  
152              
153 10         31 $mixin->IMPORT($self->NAME);
154              
155 8     8   38 no strict 'refs';
  8         12  
  8         1254  
156              
157 10         17 my $index = int(keys(%{$${"@{[$self->NAME]}::META"}{MIXIN}})) + 1;
  10         19  
  10         16  
  10         19  
158              
159 10         27 $${"@{[$self->NAME]}::META"}{MIXIN}{$mixin} = [$index, [$mixin, @args]];
  10         15  
  10         18  
160              
161 10         54 return $self;
162             }
163              
164             sub NAME {
165 783     783 1 3133 my ($self) = @_;
166              
167 783   66     3978 return ref $self || $self;
168             }
169              
170             sub ROLE {
171 44     44 1 23395 my ($self, $role, @args) = @_;
172              
173 8     8   46 no strict 'refs';
  8         10  
  8         689  
174              
175 44 0 33     62 if (!keys(%{"${role}::"}) && !${"${role}::META"} && !$$cache{$role}++) {
  44   0     184  
  0         0  
176 0 0       0 local $@; eval "require $role"; die $@ if $@;
  0         0  
  0         0  
177             }
178              
179 8     8   50 no warnings 'redefine';
  8         20  
  8         326  
180              
181 44         128 $role->IMPORT($self->NAME);
182              
183 8     8   39 no strict 'refs';
  8         24  
  8         1038  
184              
185 44         74 my $index = int(keys(%{$${"@{[$self->NAME]}::META"}{ROLE}})) + 1;
  44         76  
  44         61  
  44         82  
186              
187 44         112 $${"@{[$self->NAME]}::META"}{ROLE}{$role} = [$index, [$role, @args]];
  44         60  
  44         88  
188              
189 44         209 return $self;
190             }
191              
192             sub SUBS {
193 1     1 1 2166 my ($self) = @_;
194              
195 8     8   46 no strict 'refs';
  8         11  
  8         2688  
196              
197             return [
198 10         14 sort grep *{"@{[$self->NAME]}::$_"}{"CODE"},
  10         14  
199 1         3 grep /^[_a-zA-Z]\w*$/, keys %{"@{[$self->NAME]}::"}
  1         2  
  1         4  
200             ];
201             }
202              
203             sub TEST {
204 24     24 1 1779 my ($self, $role) = @_;
205              
206 24         79 $self->ROLE($role);
207              
208 24 50       180 $role->AUDIT($self->NAME) if $role->can('AUDIT');
209              
210 20         62 return $self;
211             }
212              
213             sub attr {
214 29     29 1 60 my ($self, $name, @args) = @_;
215              
216 29 50       61 return undef if !$name;
217 29 100       195 return $self->{$name} if !int@args;
218 2         12 return $self->{$name} = $args[0];
219             }
220              
221             1;
222              
223              
224              
225             =head1 NAME
226              
227             Mars::Kind - Kind Base Class
228              
229             =cut
230              
231             =head1 ABSTRACT
232              
233             Kind Base Class for Perl 5
234              
235             =cut
236              
237             =head1 SYNOPSIS
238              
239             package User;
240              
241             use base 'Mars::Kind';
242              
243             package main;
244              
245             my $user = User->BLESS(
246             fname => 'Elliot',
247             lname => 'Alderson',
248             );
249              
250             # bless({fname => 'Elliot', lname => 'Alderson'}, 'User')
251              
252             # i.e. BLESS is somewhat equivalent to writing
253              
254             # User->BUILD(bless(User->ARGS(User->BUILDARGS(@args) || User->DATA), 'User'))
255              
256             =cut
257              
258             =head1 DESCRIPTION
259              
260             This package provides a base class for L<"class"|Mars::Kind::Class> and
261             L<"role"|Mars::Kind::Role> (kind) derived packages and provides class building,
262             object construction, and object deconstruction lifecycle hooks. The
263             L and L packages provide a simple DSL for automating
264             L derived base classes.
265              
266             =cut
267              
268             =head1 METHODS
269              
270             This package provides the following methods:
271              
272             =cut
273              
274             =head2 args
275              
276             ARGS(Any @args) (HashRef)
277              
278             The ARGS method is a object construction lifecycle hook which accepts a list of
279             arguments and returns a blessable data structure.
280              
281             I>
282              
283             =over 4
284              
285             =item ARGS example 1
286              
287             # given: synopsis
288              
289             package main;
290              
291             my $args = User->ARGS;
292              
293             # {}
294              
295             =back
296              
297             =over 4
298              
299             =item ARGS example 2
300              
301             # given: synopsis
302              
303             package main;
304              
305             my $args = User->ARGS(name => 'Elliot');
306              
307             # {name => 'Elliot'}
308              
309             =back
310              
311             =over 4
312              
313             =item ARGS example 3
314              
315             # given: synopsis
316              
317             package main;
318              
319             my $args = User->ARGS({name => 'Elliot'});
320              
321             # {name => 'Elliot'}
322              
323             =back
324              
325             =cut
326              
327             =head2 attr
328              
329             ATTR(Str $name, Any @args) (Str | Object)
330              
331             The ATTR method is a class building lifecycle hook which installs an attribute
332             accessors in the calling package.
333              
334             I>
335              
336             =over 4
337              
338             =item ATTR example 1
339              
340             package User;
341              
342             use base 'Mars::Kind';
343              
344             User->ATTR('name');
345              
346             package main;
347              
348             my $user = User->BLESS;
349              
350             # bless({}, 'User')
351              
352             # $user->name;
353              
354             # ""
355              
356             # $user->name('Elliot');
357              
358             # "Elliot"
359              
360             =back
361              
362             =over 4
363              
364             =item ATTR example 2
365              
366             package User;
367              
368             use base 'Mars::Kind';
369              
370             User->ATTR('role');
371              
372             package main;
373              
374             my $user = User->BLESS(role => 'Engineer');
375              
376             # bless({role => 'Engineer'}, 'User')
377              
378             # $user->role;
379              
380             # "Engineer"
381              
382             # $user->role('Hacker');
383              
384             # "Hacker"
385              
386             =back
387              
388             =cut
389              
390             =head2 audit
391              
392             AUDIT(Str $role) (Str | Object)
393              
394             The AUDIT method is a class building lifecycle hook which exist in roles and is
395             executed as a callback when the consuming class invokes the L hook.
396              
397             I>
398              
399             =over 4
400              
401             =item AUDIT example 1
402              
403             package HasType;
404              
405             use base 'Mars::Kind';
406              
407             sub AUDIT {
408             die 'Consumer missing "type" attribute' if !$_[1]->can('type');
409             }
410              
411             package User;
412              
413             use base 'Mars::Kind';
414              
415             User->TEST('HasType');
416              
417             package main;
418              
419             my $user = User->BLESS;
420              
421             # Exception! Consumer missing "type" attribute
422              
423             =back
424              
425             =over 4
426              
427             =item AUDIT example 2
428              
429             package HasType;
430              
431             sub AUDIT {
432             die 'Consumer missing "type" attribute' if !$_[1]->can('type');
433             }
434              
435             package User;
436              
437             use base 'Mars::Kind';
438              
439             User->ATTR('type');
440              
441             User->TEST('HasType');
442              
443             package main;
444              
445             my $user = User->BLESS;
446              
447             # bless({}, 'User')
448              
449             =back
450              
451             =cut
452              
453             =head2 base
454              
455             BASE(Str $name) (Str | Object)
456              
457             The BASE method is a class building lifecycle hook which registers a base class
458             for the calling package. B Unlike the L hook, this hook doesn't
459             invoke the L hook.
460              
461             I>
462              
463             =over 4
464              
465             =item BASE example 1
466              
467             package Entity;
468              
469             sub work {
470             return;
471             }
472              
473             package User;
474              
475             use base 'Mars::Kind';
476              
477             User->BASE('Entity');
478              
479             package main;
480              
481             my $user = User->BLESS;
482              
483             # bless({}, 'User')
484              
485             =back
486              
487             =over 4
488              
489             =item BASE example 2
490              
491             package Engineer;
492              
493             sub debug {
494             return;
495             }
496              
497             package Entity;
498              
499             sub work {
500             return;
501             }
502              
503             package User;
504              
505             use base 'Mars::Kind';
506              
507             User->BASE('Entity');
508              
509             User->BASE('Engineer');
510              
511             package main;
512              
513             my $user = User->BLESS;
514              
515             # bless({}, 'User')
516              
517             =back
518              
519             =cut
520              
521             =head2 bless
522              
523             BLESS(Any @args) (Object)
524              
525             The BLESS method is an object construction lifecycle hook which returns an
526             instance of the calling package.
527              
528             I>
529              
530             =over 4
531              
532             =item BLESS example 1
533              
534             package User;
535              
536             use base 'Mars::Kind';
537              
538             package main;
539              
540             my $example = User->BLESS;
541              
542             # bless({}, 'User')
543              
544             =back
545              
546             =over 4
547              
548             =item BLESS example 2
549              
550             package User;
551              
552             use base 'Mars::Kind';
553              
554             package main;
555              
556             my $example = User->BLESS(name => 'Elliot');
557              
558             # bless({name => 'Elliot'}, 'User')
559              
560             =back
561              
562             =over 4
563              
564             =item BLESS example 3
565              
566             package User;
567              
568             use base 'Mars::Kind';
569              
570             package main;
571              
572             my $example = User->BLESS({name => 'Elliot'});
573              
574             # bless({name => 'Elliot'}, 'User')
575              
576             =back
577              
578             =cut
579              
580             =over 4
581              
582             =item BLESS example 4
583              
584             package List;
585              
586             use base 'Mars::Kind';
587              
588             sub ARGS {
589             my ($self, @args) = @_;
590              
591             return @args
592             ? ((@args == 1 && ref $args[0] eq 'ARRAY') ? @args : [@args])
593             : $self->DATA;
594             }
595              
596             sub DATA {
597             my ($self, $data) = @_;
598              
599             return $data ? [@$data] : [];
600             }
601              
602             package main;
603              
604             my $list = List->BLESS(1..4);
605              
606             # bless([1..4], 'List')
607              
608             =back
609              
610             =cut
611              
612             =over 4
613              
614             =item BLESS example 5
615              
616             package List;
617              
618             use base 'Mars::Kind';
619              
620             sub ARGS {
621             my ($self, @args) = @_;
622              
623             return @args
624             ? ((@args == 1 && ref $args[0] eq 'ARRAY') ? @args : [@args])
625             : $self->DATA;
626             }
627              
628             sub DATA {
629             my ($self, $data) = @_;
630              
631             return $data ? [@$data] : [];
632             }
633              
634             package main;
635              
636             my $list = List->BLESS([1..4]);
637              
638             # bless([1..4], 'List')
639              
640             =back
641              
642             =cut
643              
644             =head2 build
645              
646             BUILD(HashRef $data) (Object)
647              
648             The BUILD method is an object construction lifecycle hook which receives an
649             object and the data structure that was blessed, and should return an object
650             although its return value is ignored by the L hook.
651              
652             I>
653              
654             =over 4
655              
656             =item BUILD example 1
657              
658             package User;
659              
660             use base 'Mars::Kind';
661              
662             sub BUILD {
663             my ($self) = @_;
664              
665             $self->{name} = 'Mr. Robot';
666              
667             return $self;
668             }
669              
670             package main;
671              
672             my $example = User->BLESS(name => 'Elliot');
673              
674             # bless({name => 'Mr. Robot'}, 'User')
675              
676             =back
677              
678             =over 4
679              
680             =item BUILD example 2
681              
682             package User;
683              
684             use base 'Mars::Kind';
685              
686             sub BUILD {
687             my ($self) = @_;
688              
689             $self->{name} = 'Mr. Robot';
690              
691             return $self;
692             }
693              
694             package Elliot;
695              
696             use base 'User';
697              
698             sub BUILD {
699             my ($self, $data) = @_;
700              
701             $self->SUPER::BUILD($data);
702              
703             $self->{name} = 'Elliot';
704              
705             return $self;
706             }
707              
708             package main;
709              
710             my $elliot = Elliot->BLESS;
711              
712             # bless({name => 'Elliot'}, 'Elliot')
713              
714             =back
715              
716             =cut
717              
718             =head2 buildargs
719              
720             BUILDARGS(Any @args) (Any @args | HashRef $data)
721              
722             The BUILDARGS method is an object construction lifecycle hook which receives
723             the arguments provided to the constructor (unaltered) and should return a list
724             of arguments, a hashref, or key/value pairs.
725              
726             I>
727              
728             =over 4
729              
730             =item BUILDARGS example 1
731              
732             package User;
733              
734             use base 'Mars::Kind';
735              
736             sub BUILD {
737             my ($self) = @_;
738              
739             return $self;
740             }
741              
742             sub BUILDARGS {
743             my ($self, @args) = @_;
744              
745             my $data = @args == 1 && !ref $args[0] ? {name => $args[0]} : {};
746              
747             return $data;
748             }
749              
750             package main;
751              
752             my $user = User->BLESS('Elliot');
753              
754             # bless({name => 'Elliot'}, 'User')
755              
756             =back
757              
758             =cut
759              
760             =head2 data
761              
762             DATA() (Ref)
763              
764             The DATA method is an object construction lifecycle hook which returns the
765             default data structure reference to be blessed when no arguments are provided
766             to the constructor. The default data structure is an empty hashref.
767              
768             I>
769              
770             =over 4
771              
772             =item DATA example 1
773              
774             package Example;
775              
776             use base 'Mars::Kind';
777              
778             sub DATA {
779             return [];
780             }
781              
782             package main;
783              
784             my $example = Example->BLESS;
785              
786             # bless([], 'Example')
787              
788             =back
789              
790             =over 4
791              
792             =item DATA example 2
793              
794             package Example;
795              
796             use base 'Mars::Kind';
797              
798             sub DATA {
799             return {};
800             }
801              
802             package main;
803              
804             my $example = Example->BLESS;
805              
806             # bless({}, 'Example')
807              
808             =back
809              
810             =cut
811              
812             =head2 destroy
813              
814             DESTROY() (Any)
815              
816             The DESTROY method is an object destruction lifecycle hook which is called when
817             the last reference to the object goes away.
818              
819             I>
820              
821             =over 4
822              
823             =item DESTROY example 1
824              
825             package User;
826              
827             use base 'Mars::Kind';
828              
829             our $USERS = 0;
830              
831             sub BUILD {
832             return $USERS++;
833             }
834              
835             sub DESTROY {
836             return $USERS--;
837             }
838              
839             package main;
840              
841             my $user = User->BLESS(name => 'Elliot');
842              
843             undef $user;
844              
845             # 1
846              
847             =back
848              
849             =cut
850              
851             =head2 does
852              
853             DOES(Str $name) (Bool)
854              
855             The DOES method returns true or false if the invocant consumed the role or
856             interface provided.
857              
858             I>
859              
860             =over 4
861              
862             =item DOES example 1
863              
864             package Admin;
865              
866             use base 'Mars::Kind';
867              
868             package User;
869              
870             use base 'Mars::Kind';
871              
872             User->ROLE('Admin');
873              
874             sub BUILD {
875             return;
876             }
877              
878             sub BUILDARGS {
879             return;
880             }
881              
882             package main;
883              
884             my $admin = User->DOES('Admin');
885              
886             # 1
887              
888             =back
889              
890             =over 4
891              
892             =item DOES example 2
893              
894             package Admin;
895              
896             use base 'Mars::Kind';
897              
898             package User;
899              
900             use base 'Mars::Kind';
901              
902             User->ROLE('Admin');
903              
904             sub BUILD {
905             return;
906             }
907              
908             sub BUILDARGS {
909             return;
910             }
911              
912             package main;
913              
914             my $is_owner = User->DOES('Owner');
915              
916             # 0
917              
918             =back
919              
920             =cut
921              
922             =head2 export
923              
924             EXPORT(Any @args) (ArrayRef)
925              
926             The EXPORT method is a class building lifecycle hook which returns an arrayref
927             of routine names to be automatically imported by the calling package whenever
928             the L or L hooks are used.
929              
930             I>
931              
932             =over 4
933              
934             =item EXPORT example 1
935              
936             package Admin;
937              
938             use base 'Mars::Kind';
939              
940             sub shutdown {
941             return;
942             }
943              
944             sub EXPORT {
945             ['shutdown']
946             }
947              
948             package User;
949              
950             use base 'Mars::Kind';
951              
952             User->ROLE('Admin');
953              
954             package main;
955              
956             my $user = User->BLESS;
957              
958             # bless({}, 'User')
959              
960             =back
961              
962             =cut
963              
964             =head2 from
965              
966             FROM(Str $name) (Str | Object)
967              
968             The FROM method is a class building lifecycle hook which registers a base class
969             for the calling package, automatically invoking the L hook on the base
970             class.
971              
972             I>
973              
974             =over 4
975              
976             =item FROM example 1
977              
978             package Entity;
979              
980             use base 'Mars::Kind';
981              
982             sub AUDIT {
983             my ($self, $from) = @_;
984             die "Missing startup" if !$from->can('startup');
985             die "Missing shutdown" if !$from->can('shutdown');
986             }
987              
988             package User;
989              
990             use base 'Mars::Kind';
991              
992             User->ATTR('startup');
993             User->ATTR('shutdown');
994              
995             User->FROM('Entity');
996              
997             package main;
998              
999             my $user = User->BLESS;
1000              
1001             # bless({}, 'User')
1002              
1003             =back
1004              
1005             =over 4
1006              
1007             =item FROM example 2
1008              
1009             package Entity;
1010              
1011             use base 'Mars::Kind';
1012              
1013             sub AUDIT {
1014             my ($self, $from) = @_;
1015             die "Missing startup" if !$from->can('startup');
1016             die "Missing shutdown" if !$from->can('shutdown');
1017             }
1018              
1019             package User;
1020              
1021             use base 'Mars::Kind';
1022              
1023             User->FROM('Entity');
1024              
1025             sub startup {
1026             return;
1027             }
1028              
1029             sub shutdown {
1030             return;
1031             }
1032              
1033             package main;
1034              
1035             my $user = User->BLESS;
1036              
1037             # bless({}, 'User')
1038              
1039             =back
1040              
1041             =cut
1042              
1043             =head2 import
1044              
1045             IMPORT(Str $into, Any @args) (Str | Object)
1046              
1047             The IMPORT method is a class building lifecycle hook which dispatches the
1048             L lifecycle hook whenever the L or L hooks are used.
1049              
1050             I>
1051              
1052             =over 4
1053              
1054             =item IMPORT example 1
1055              
1056             package Admin;
1057              
1058             use base 'Mars::Kind';
1059              
1060             our $USES = 0;
1061              
1062             sub shutdown {
1063             return;
1064             }
1065              
1066             sub EXPORT {
1067             ['shutdown']
1068             }
1069              
1070             sub IMPORT {
1071             my ($self, $into) = @_;
1072              
1073             $self->SUPER::IMPORT($into);
1074              
1075             $USES++;
1076              
1077             return $self;
1078             }
1079              
1080             package User;
1081              
1082             use base 'Mars::Kind';
1083              
1084             User->ROLE('Admin');
1085              
1086             package main;
1087              
1088             my $user = User->BLESS;
1089              
1090             # bless({}, 'User')
1091              
1092             =back
1093              
1094             =cut
1095              
1096             =head2 meta
1097              
1098             META() (Meta)
1099              
1100             The META method return a L object which describes the invocant's
1101             configuration.
1102              
1103             I>
1104              
1105             =over 4
1106              
1107             =item META example 1
1108              
1109             package User;
1110              
1111             use base 'Mars::Kind';
1112              
1113             package main;
1114              
1115             my $meta = User->META;
1116              
1117             # bless({name => 'User'}, 'Mars::Meta')
1118              
1119             =back
1120              
1121             =cut
1122              
1123             =head2 name
1124              
1125             NAME() (Str)
1126              
1127             The NAME method is a class building lifecycle hook which returns the name of
1128             the package.
1129              
1130             I>
1131              
1132             =over 4
1133              
1134             =item NAME example 1
1135              
1136             package User;
1137              
1138             use base 'Mars::Kind';
1139              
1140             package main;
1141              
1142             my $name = User->NAME;
1143              
1144             # "User"
1145              
1146             =back
1147              
1148             =over 4
1149              
1150             =item NAME example 2
1151              
1152             package User;
1153              
1154             use base 'Mars::Kind';
1155              
1156             package main;
1157              
1158             my $name = User->BLESS->NAME;
1159              
1160             # "User"
1161              
1162             =back
1163              
1164             =cut
1165              
1166             =head2 role
1167              
1168             ROLE(Str $name) (Str | Object)
1169              
1170             The ROLE method is a class building lifecycle hook which consumes the role
1171             provided, automatically invoking the role's L hook. B Unlike
1172             the L and L hooks, this hook doesn't invoke the L hook.
1173             The role composition semantics are as follows: Routines to be consumed must be
1174             explicitly declared via the L hook. Routines will be copied to the
1175             consumer unless they already exist (excluding routines from base classes, which
1176             will be overridden). If multiple roles are consumed having routines with the
1177             same name (i.e. naming collisions) the first routine copied wins.
1178              
1179             I>
1180              
1181             =over 4
1182              
1183             =item ROLE example 1
1184              
1185             package Admin;
1186              
1187             use base 'Mars::Kind';
1188              
1189             package User;
1190              
1191             use base 'Mars::Kind';
1192              
1193             User->ROLE('Admin');
1194              
1195             package main;
1196              
1197             my $admin = User->DOES('Admin');
1198              
1199             # 1
1200              
1201             =back
1202              
1203             =over 4
1204              
1205             =item ROLE example 2
1206              
1207             package Create;
1208              
1209             use base 'Mars::Kind';
1210              
1211             package Delete;
1212              
1213             use base 'Mars::Kind';
1214              
1215             package Manage;
1216              
1217             use base 'Mars::Kind';
1218              
1219             Manage->ROLE('Create');
1220             Manage->ROLE('Delete');
1221              
1222             package User;
1223              
1224             use base 'Mars::Kind';
1225              
1226             User->ROLE('Manage');
1227              
1228             package main;
1229              
1230             my $create = User->DOES('Create');
1231              
1232             # 1
1233              
1234             =back
1235              
1236             =cut
1237              
1238             =head2 subs
1239              
1240             SUBS() (ArrayRef)
1241              
1242             The SUBS method returns the routines defined on the package and consumed from
1243             roles, but not inherited by superclasses.
1244              
1245             I>
1246              
1247             =over 4
1248              
1249             =item SUBS example 1
1250              
1251             package Example;
1252              
1253             use base 'Mars::Kind';
1254              
1255             package main;
1256              
1257             my $subs = Example->SUBS;
1258              
1259             # [...]
1260              
1261             =back
1262              
1263             =cut
1264              
1265             =head2 test
1266              
1267             TEST(Str $name) (Str | Object)
1268              
1269             The TEST method is a class building lifecycle hook which consumes the role
1270             provided, automatically invoking the role's L hook as well as the
1271             L hook if defined.
1272              
1273             I>
1274              
1275             =over 4
1276              
1277             =item TEST example 1
1278              
1279             package Admin;
1280              
1281             use base 'Mars::Kind';
1282              
1283             sub AUDIT {
1284             my ($self, $from) = @_;
1285             die "Missing startup" if !$from->can('startup');
1286             die "Missing shutdown" if !$from->can('shutdown');
1287             }
1288              
1289             sub AUDIT_BUILD {
1290             my ($self, $data) = @_;
1291             die "Attribute 'startup' can't be undefined" if !$self->startup;
1292             die "Attribute 'shutdown' can't be undefined" if !$self->shutdown;
1293             }
1294              
1295             package User;
1296              
1297             use base 'Mars::Kind';
1298              
1299             User->ATTR('startup');
1300             User->ATTR('shutdown');
1301              
1302             User->TEST('Admin');
1303              
1304             sub BUILD {
1305             my ($self, $data) = @_;
1306             # Using AUDIT_BUILD as a callback
1307             $self->Admin::AUDIT_BUILD($data);
1308             }
1309              
1310             package main;
1311              
1312             my $user = User->BLESS(startup => 'hello');
1313              
1314             # Exception! Attribute 'shutdown' can't be undefined
1315              
1316             =back
1317              
1318             =cut
1319              
1320             =head1 AUTHORS
1321              
1322             Awncorp, C
1323              
1324             =cut