File Coverage

blib/lib/Package/Base.pm
Criterion Covered Total %
statement 33 34 97.0
branch 6 6 100.0
condition n/a
subroutine 11 12 91.6
pod 5 5 100.0
total 55 57 96.4


line stmt bran cond sub pod time code
1             =head1 NAME
2              
3             Package::Base - An abstract base for implementation classes to inherit from
4              
5             =head1 SYNOPSIS
6              
7             #don't use this module directly, but rather inherit from it.
8             package My::Package;
9             use base qw(Package::Base);
10              
11             #define a couple of get/setters
12             sub slot1 {
13             my($self,$val) = @_;
14             $self->{'slot1'} = $val if defined($val);
15             return $self->{'slot1'};
16             }
17              
18             sub slot2 {
19             my($self,$val) = @_;
20             $self->{'slot2'} = $val if defined($val);
21             return $self->{'slot2'};
22             }
23              
24             package main:
25             my $object = My::Package->new(slot1 => 'value1', slot2 => 'value2', slot3 => 'value3');
26             #slot3 => 'value3' is silently ignored
27              
28             $object->slot1; #returns 'value1'
29             $object->slot2; #returns 'value2'
30             $object->slot3; #error, method undefined
31              
32             =head1 DESCRIPTION
33              
34             Package::Base is an abstract base class, meaning it isn't intended to be used directly,
35             but rather inherited from by an instantiable class. In fact, attempting to instantiate
36             a Package::Base object directly will result in an error.
37              
38             B
39              
40             B
41              
42             * a built-in new() method that does instantiation of a hash based object
43              
44             * new() accepts an anonymous hash as arguments (a list of key/value pairs, essentially).
45             and sets attributes appropriately within your object if methods of the same name
46             as the keys are found.
47              
48             * Package::Base::Devel is a subclass specifically designed for debugging Perl classes
49             is bundled with Package::Base, and the inherited interface works the same way. This
50             means that while developing/debugging a module, you can do:
51              
52             package My::Package;
53             use base qw(Package::Base::Devel);
54              
55             #...
56              
57             and have nice Log::Log4perl logging about what your method is doing sent to a file,
58             filehandle, email, database... whatever (see L for details about this
59             amazing logging API). Then, when you're ready to ship, just change the line:
60              
61             package My::Package;
62             -use base qw(Package::Base::Devel);
63             +use base qw(Package::Base);
64              
65             and the heavy debugging toll paid for the debug logging vanishes.
66              
67             * Package::Base comes with a pstub, a drop-in replacement for h2xs if you're writing
68             a module that doesn't rely on Perl XS or C files.
69              
70             Now to be "fair and balanced" :)
71              
72             B
73              
74             B
75              
76             * Package::Base currently only works for hash-based objects. This may be extended to
77             support array-based objects in the future.
78              
79             * Package::Base assumes you have methods overloaded to act as accessors/mutators.
80             e.g. calling C<$obj->foo(1)> sets object's foo attribute to 1, and calling
81             C<$obj->foo()> retrieves object's foo attribute's value. See L
82             for an easy way to set these up.
83              
84             * Package::Base tries to initialize slots for all passed key/value pairs, instead of
85             allowing the constructor, new(), to filter out only those it wants. Class::Base
86             allows filtering like this.
87              
88             =head1 AUTHOR
89              
90             Allen Day, Eallenday@ucla.eduE
91              
92             =head1 SEE ALSO
93              
94             For another way to do it, see L.
95              
96             L.
97              
98             =cut
99              
100             #these Package::Base::Stub classes
101             package Package::Base::Stub::Log;
102 3     3   828 use strict;
  3         7  
  3         98  
103 3     3   2863 use AutoLoader;
  3         22039  
  3         21  
104              
105             my $instance = undef;
106              
107             sub get_instance {
108 4     4   7 my $class = shift;
109 4 100       15 if(!$instance){
110 2         28 $instance = bless {}, $class;
111             } else {
112 2         14 return $instance;
113             }
114             }
115              
116              
117             #=head2 AUTOLOAD()
118             #
119             #method to support swapability of Package::Base and Package::Base::Devel.
120             #returns 1
121             #
122             #this means all method calls succeed, and everything but get_instance()
123             #is a no-op.
124             #
125             #=cut
126              
127             sub AUTOLOAD {
128 4     4   12 return 1;
129             }
130              
131             package Package::Base;
132              
133 3     3   482 use strict;
  3         12  
  3         191  
134 3     3   6857 use Data::Dumper;
  3         44162  
  3         239  
135 3     3   26 use Carp qw(cluck);
  3         15  
  3         853  
136              
137             our $VERSION = '0.03';
138              
139             =head1 METHODS
140              
141             =head2 new()
142              
143             Usage : This is an abstract constructor, and can't be called directly.
144             Use it by either calling it from your subclass directly, e.g.:
145              
146             package My::Class;
147             use base qw(Package::Base);
148              
149             sub new {
150             my($class,%arg) = @_;
151             my $self = $class->SUPER::new();
152             return $self
153             }
154              
155             or by not declaring a new() method at all, and letting your class
156             inherit the new() method at object construction time.
157              
158             Function: Provides universal construction for hash-based objects.
159             Returns : An object reference of the calling class, or undef if an attempt is made
160             to instantiate Package::Base directly.
161             Args : an anonymous hash of object attribute/value pairs. L.
162              
163             =cut
164              
165             sub new {
166 11     11 1 1409 my($class,%arg) = @_;
167              
168 11 100       36 if($class eq __PACKAGE__){
169 1         353 cluck( __PACKAGE__." is an abstract base class, and not directly instantiable" );
170 1         6 return undef;
171             }
172              
173 10         27 my $self = bless {}, $class;
174 10         50 $self->init(%arg);
175              
176 10         45 return $self;
177             }
178              
179             =head2 init()
180              
181             Usage : $object->init(key1 => 'value1', key2 => 'value2');
182             Returns : a reference to the calling object
183             Args : an anonymous hash of object attribute/value pairs.
184             Function:
185              
186             a method to initialize a new object. Package::Base::init() provides
187             the following functionality:
188              
189             1. treats arguments as an anonymous hash, and calls set-type methods
190             if possible for each key/value pair. Consider the following code:
191              
192             package My::Class;
193             use base qw(Package::Base);
194              
195             sub meth { my($self,$arg) = @_;
196             $self->{'foo'} = $arg if defined($arg);
197             return $self->{'foo'}
198             }
199              
200             package main;
201             my $foo = My::Class->new(meth => 'some value');
202             print $foo->meth(); #prints "some value"
203              
204             If method meth() was not defined in My::Class, or any of My::Class's
205             superclasses, the key/value pair is silently ignored. Take advantage
206             of this method as well as any custom initialization you need in your
207             subclass like this:
208              
209             package My::Class;
210             use base qw(Package::Base);
211              
212             sub init {
213             my($self,%arg) = @_;
214             $self->SUPER::init(@_);
215              
216             # now do your stuff
217             }
218              
219             =cut
220              
221             sub init {
222 10     10 1 43 my($self,%arg) = @_;
223 10         32 foreach my $a (keys %arg){
224 6 100       70 $self->$a($arg{$a}) if $self->can($a);
225             }
226              
227 10         41 return $self;
228             }
229              
230             =head1 SWAP-IN/OUT METHODS FOR Package::Base::Devel
231              
232             these methods allow the interchangeable usage of Package::Base
233             and Package::Base::Devel. They're essentially no-op methods.
234              
235             =cut
236              
237             =head2 log()
238              
239             returns a singleton instance of an object that accepts
240             Log::Log4perl::Logger calls (any calls, actually, it ISA
241             Autoloader), but does nothing with them.
242              
243             =cut
244              
245             sub log {
246 4     4 1 464 return Package::Base::Stub::Log->get_instance();
247             }
248              
249             =head2 loglevel()
250              
251             method to support swapability of Package::Base and Package::Base::Devel.
252             returns 1
253              
254             =cut
255              
256 7     7 1 25 sub loglevel {1}
257              
258             =head2 logconfig()
259              
260             method to support swapability of Package::Base and Package::Base::Devel.
261             returns 1
262              
263             =cut
264              
265 0     0 1   sub logconfig {1}
266              
267             1;
268             __END__