File Coverage

blib/lib/enum/fields.pm
Criterion Covered Total %
statement 43 44 97.7
branch 11 12 91.6
condition 2 2 100.0
subroutine 7 7 100.0
pod 0 1 0.0
total 63 66 95.4


line stmt bran cond sub pod time code
1             package enum::fields;
2              
3 1     1   790 use 5.00503;
  1         4  
  1         46  
4 1     1   6 use strict;
  1         3  
  1         36  
5 1     1   14 no strict 'refs';
  1         2  
  1         40  
6 1     1   7 use vars qw($VERSION %class_info %final);
  1         1  
  1         79  
7              
8 1     1   6 use Carp;
  1         2  
  1         550  
9              
10             $VERSION = '1.0';
11              
12             %class_info = ();
13             %final = ();
14              
15             sub define_constant {
16              
17 17     17 0 22 my $pkg = shift;
18 17         18 my $const = shift;
19 17         17 my $val = shift;
20            
21             # Stolen from base.pm, but hey, that's what code's for
22            
23 17         12 my $glob;
24            
25 17 100 100     17 if (defined($glob = ${"$pkg\::"}{$const}) and *{$glob}{CODE}) {
  17         80  
  1         8  
26 1         235 croak "Redefined constant $const";
27             }
28            
29 16         1357 eval "*$pkg\::$const = sub () { $val }";
30             }
31              
32             sub import {
33              
34 8     8   2262 shift;
35            
36 8         23 my $class = caller();
37            
38             # Who needs exporter
39            
40 8 100       21 if ($class =~ /^enum::fields::/) {
41 1         3 *{"$class\::class_info"} = \%class_info;
  1         5  
42 1         2 *{"$class\::define_constant"} = \&define_constant;
  1         7  
43 1         2 *{"$class\::final"} = \%final;
  1         11  
44             }
45            
46 8 100       271 return unless (@_);
47            
48 7 100       235 croak "Cannot add fields to class that has been inherited"
49             if exists($final{$class});
50            
51 6 100       16 $class_info{$class} = [] unless exists($class_info{$class});
52            
53 6         9 my $idx = ~~@{$class_info{$class}};
  6         12  
54            
55 6         10 for my $fld (@_) {
56 11         28 define_constant($class, $fld, $idx++);
57 10 50       32 if ($@) {
58 0         0 croak();
59             }
60 10         12 push @{$class_info{$class}}, $fld;
  10         196  
61             }
62             }
63              
64             1;
65              
66             =pod
67              
68             =head1 NAME
69              
70             enum::fields - Perl extension for defining constants for use
71             in Array-based objects
72              
73             =head1 SYNOPSIS
74              
75             package Foo;
76            
77             use enum::fields qw{
78             FIELD_ONE
79             FIELD_TWO
80             };
81            
82             package Bar;
83            
84             use base 'Foo';
85            
86             use enum::fields::extending Foo => qw{
87             BAR_FIELD_ONE
88             BAR_FIELD_TWO
89             };
90              
91             =head1 DESCRIPTION
92              
93             This module allows you to define constants that can be
94             inherited and extended by child classes. It is used
95             much like a simple form of L to define constants,
96             with the exception that you can inherit a list of constants
97             from a parent class using the "extending" form of the pragma.
98              
99             This module was designed to allow an object-oriented programmer
100             to use an array to store instance data for object classes.
101              
102             Since I'm a lousy doc writer I'll get right to the examples.
103              
104             =head2 Example 1 - Parent Class
105              
106             package Employee;
107            
108             use enum::fields qw{NAME PHONE SALARY};
109            
110             sub new {
111             my $class = shift;
112             my $self = bless [], $class;
113              
114             $self->[NAME] = shift;
115             $self->[PHONE] = shift;
116             $self->[SALARY] = shift;
117             }
118            
119             sub salary {
120             my $self = shift;
121             $self->[SALARY] = shift if (@_);
122             $self->[SALARY];
123             }
124              
125             This example shows a simple employee object. It holds the
126             employee's name, phone, and salary information. The constructor
127             for this class, aptly named 'new', creates a new employee and
128             assigns the three arguments passed in to the NAME, PHONE, and
129             SALARY fields (whose values, not-so-coincidentally, are 0, 1,
130             and 2). Since this is actually an array storage, it is nice
131             and fast.
132              
133             =head2 Example 2 - Subclassing without adding fields
134              
135             package Employee::CoffeeBoy;
136            
137             use Carp;
138            
139             use base 'Employee';
140             use enum::fields::extending 'Employee';
141              
142             sub salary {
143             my $self = shift;
144             if (@_) {
145             $salary = shift;
146             if ($salary > 8_000.00) {
147             croak "Attept to overpay coffee boy";
148             }
149             $self->[SALARY] = $salary;
150             }
151             $self->[SALARY];
152             }
153              
154             This example shows a subclass that inherits from Employee.
155             Using the L pragma causes the fields
156             from the parent class to be brought into the child class.
157             Therefore we are able to override the I method.
158              
159             =head2 Example 3 - Subclassing with adding fields
160              
161             package Employee::CEO;
162            
163             use base 'Employee';
164             use enum::fields::extending Employee => qw{
165             NUMBER_OF_BOATS
166             };
167            
168             sub boats {
169             my $self = shift;
170             $self->[NUMBER_OF_BOATS] = shift if (@_);
171             $self->[NUMBER_OF_BOATS];
172             }
173              
174             This class shows that we can inherit the fields from a
175             parent, and then add another field onto the end of the
176             list. Behind the scenes, the new field is numbered
177             after those from the parent class, so that the inherited
178             fields and the new fields will not collide.
179              
180             =head1 CAVEATS
181              
182             You cannot add fields to a class after another class has
183             inherited its fields. Attempting to do so will result in
184             a compile-time error.
185              
186             Trying to extend fields from more than one class (ala
187             multiple inheritance) will not work. For a different
188             (arguably better) solution, see L.
189              
190             =head1 SEE ALSO
191              
192             L, L.
193              
194             =head1 AUTHOR
195              
196             David M. Lloyd Edmlloyd@cpan.orgE
197              
198             =head1 COPYRIGHT AND LICENSE
199              
200             Copyright (C) 2002 by David M. Lloyd
201              
202             This library is free software; you can redistribute it and/or modify
203             it under the same terms as Perl itself.
204              
205             =cut