File Coverage

lib/Package/Data/Inheritable.pm
Criterion Covered Total %
statement 88 89 98.8
branch 15 28 53.5
condition n/a
subroutine 15 15 100.0
pod 3 3 100.0
total 121 135 89.6


line stmt bran cond sub pod time code
1 14     14   429442 use warnings;
  14         86  
  14         405  
2 14     14   75 use strict;
  14         28  
  14         402  
3 14     14   416 use 5.006_000; # Perl >=5.6.0 we need 'our' and other stuff
  14         50  
  14         1021  
4              
5             package Package::Data::Inheritable;
6 14     14   83 use base qw( Exporter );
  14         31  
  14         1300  
7              
8 14     14   77 use Carp;
  14         27  
  14         2237  
9              
10             our $VERSION = '0.05';
11              
12              
13             # This method carries out the actual package variable inheritance via export
14             # <$class> Is the package/class which is exporting
15             # <$caller> Is the package/class into which we're exporting
16             # <@symbols> Is the list of symbols requested for import.
17             # This does not make sense for this module since we do not export
18             # syms, we rather propagate to our children classes and they
19             # should not be able to control what to inherit
20             sub inherit {
21 37     37 1 12701 my ($class, @symbols) = @_;
22 37 50       117 croak __PACKAGE__ . "::inherit: Extra params specified. (@symbols)" if @symbols;
23              
24 37         114 my ($caller, $file, $line) = caller;
25 14     14   77 no strict "refs";
  14         30  
  14         3196  
26              
27             # propagate inherited fields up to our caller
28 37         56 my @inherited;
29             {
30             # collect inherited fields from all superclasses
31 37         52 my @inherited = $class->_get_inherited_from_parent();
  37         222  
32             # ... and add them to those that this class wants to make inheritable
33 37         50 push @{$class ."::EXPORT_INHERIT"}, @inherited;
  37         128  
34              
35             # and now push onto EXPORT_OK everything we want to be inheritable
36 37         43 push @{$class ."::EXPORT_OK"}, @{$class ."::EXPORT_INHERIT"};
  37         108  
  37         174  
37             }
38             # make Exporter export our INHERITANCE fields together with the usual @EXPORT
39 37         58 push @symbols, (@inherited, @{$class ."::EXPORT_INHERIT"});
  37         137  
40 37         54 push @symbols, @{$class ."::EXPORT"};
  37         101  
41              
42             # handle derived class (our caller) overriden fields
43 37         47 foreach my $overriden (@{$caller .'::EXPORT_INHERIT'}) {
  37         151  
44 24         43 @symbols = grep { $_ ne $overriden } @symbols;
  150         501  
45             }
46              
47 37         25521 $class->export_to_level(1, $class, @symbols);
48             }
49              
50              
51             # static method
52             # Make a static field inheritable by adding it to @EXPORT_INHERIT
53             sub pkg_inheritable {
54 69     69 1 1331 my ($callpkg, $symbol, $value) = @_;
55 69 50       1549 ref $callpkg and croak "pkg_inheritable: called on a reference: $callpkg";
56              
57 14     14   75 no strict "refs";
  14         26  
  14         2801  
58 69         73 my $export_ok = \@{"${callpkg}::EXPORT_INHERIT"};
  69         215  
59 93         227 croak "pkg_inheritable: trying to redefine symbol '$symbol' in package $callpkg"
60 69 50       142 if grep { $_ eq $symbol } @$export_ok;
61              
62 69 50       289 $symbol =~ s/^(\W)// or croak "pkg_inheritable: no sigil in symbol '$symbol'";
63 69         131 my $sigil = $1;
64 69         125 my $qualified_symbol = "${callpkg}::$symbol";
65              
66 14     14   80 no strict 'vars';
  14         27  
  14         2641  
67 69         73 *pkg_stash = *{"${callpkg}::"};
  69         155  
68              
69             # install in the caller symbol table a new symbol
70             # this will override any already existing one
71             *$qualified_symbol =
72             $sigil eq '&' ? \&$value :
73             $sigil eq '$' ? \$value :
74             $sigil eq '@' ? \@$value :
75             $sigil eq '%' ? \%$value :
76             $sigil eq '*' ? \*$value :
77 69 0       344 do { Carp::croak("Can't install symbol: $sigil$symbol") };
  0 0       0  
    50          
    100          
    50          
78              
79 69         746 push @$export_ok, "$sigil$symbol";
80             }
81              
82             # static method
83             # Make a static field inheritable by adding it to @EXPORT_INHERIT
84             # make it const if it's a scalar, croak otherwise
85             sub pkg_const_inheritable {
86 8     8 1 10149 my ($callpkg, $symbol, $value) = @_;
87 8 50       21 ref $callpkg and croak "pkg_const_inheritable: called on a reference: $callpkg";
88              
89 14     14   81 no strict "refs";
  14         30  
  14         8107  
90 8         9 my $export_ok = \@{"${callpkg}::EXPORT_INHERIT"};
  8         25  
91 24         59 croak "pkg_const_inheritable: trying to redefine symbol '$symbol' in package $callpkg"
92 8 50       17 if grep { $_ eq $symbol } @$export_ok;
93              
94 8 100       173 $symbol =~ s/^(\W)// or croak "pkg_const_inheritable: no sigil in symbol '$symbol'";
95 7         15 my $sigil = $1;
96 7         18 my $qualified_symbol = "${callpkg}::$symbol";
97 7 100       686 croak "pkg_const_inheritable: not a scalar, cannot make const symbol '$symbol'"
98             if $sigil ne '$';
99              
100 14     14   216 no strict 'vars';
  14         29  
  14         2028  
101 3         6 *pkg_stash = *{"${callpkg}::"};
  3         7  
102              
103             # install in the caller symbol table a new symbol
104             # this will override any already existing one
105 3         157 eval "*$qualified_symbol = \\'$value'";
106 3 50       11 croak "Cannot install constant symbol $qualified_symbol: $@" if $@;
107              
108 3         2507 push @$export_ok, "$sigil$symbol";
109             }
110              
111              
112             # collect inherited fields from all superclasses
113             sub _get_inherited_from_parent {
114 37     37   58 my ($class) = @_;
115              
116 14     14   73 no strict "refs";
  14         28  
  14         2374  
117 37         39 my @inherited;
118 37         43 foreach my $super (@{$class . "::ISA"}) {
  37         120  
119 37         48 push @inherited, @{$super . "::EXPORT_INHERIT"};
  37         183  
120             }
121 37         139 return @inherited;
122             }
123              
124              
125              
126             =head1 NAME
127              
128             Package::Data::Inheritable - Inheritable and overridable package data/variables
129              
130             =head1 VERSION
131              
132             Version 0.05
133              
134             =cut
135              
136             =head1 SYNOPSIS
137              
138             use strict;
139             package Base;
140             use base qw( Package::Data::Inheritable );
141              
142             BEGIN {
143             Base->pkg_inheritable('$foo' => 'a not so ordinary package variable');
144             }
145              
146             print $foo;
147              
148              
149             package Derived;
150             use base qw( Base );
151              
152             BEGIN {
153             Derived->pkg_inheritable('$bar');
154             Derived->pkg_inheritable('@baz' => [1,2,3]);
155              
156             inherit Base;
157             }
158              
159             print $foo,
160             @baz, $bar;
161              
162             =head1 DESCRIPTION
163              
164             This module tries to deliver inheritable package data (variables) with a reasonably
165             convenient interface.
166             After declaration the variables can be used like ordinary package variables. Most
167             importantly, these variables can be inherited by derived classes (packages) by
168             calling the inherit() method.
169             If a derived class doesn't call inherit() it will still be able to define its
170             variables and make them inheritable by its subclasses.
171             Scalar variables can be declared constant.
172              
173             Within your class (hierarchy) code you will benefit from compiler checks on those
174             variables. The overall result is close to real class data members.
175             Of course you can wrap your variables in accessor/mutators methods as you need.
176              
177             The semantic provided mimics the class data members in languages like C++ and Java.
178             When you assign to an inherited variable within a derived class, every class
179             in the inheritance hierarchy will see the new value. If you want to override a
180             variable you must redeclare it explicitly.
181              
182             To declare inheritable variables two interfaces are provided:
183             a method interface via pkg_inheritable() and pkg_const_inheritable().
184             an Exporter-like interface, via the array @EXPORT_INHERIT.
185              
186             Inheriting always requires invoking the inherit() method.
187             The variable visibility (scope) depends on the interface you used. If you use
188             the Exporter-like interface, variables will be declared via our, while if you
189             use the method interface it will be like you had imported those variables.
190             The Exporter like interface does not currently support constants.
191              
192             =head1 EXPORT
193              
194             Package::Data::Inheritable is an Exporter, inheriting from it (via use base or @ISA)
195             will make your class an Exporter as well.
196             The package variable @EXPORT_INHERIT contains the symbols that will be inherited
197             and @EXPORT_OK will always contain at least those symbols.
198              
199             The Exporter like interface allows your class to set @EXPORT_INHERIT in pretty
200             much the same way you would set @EXPORT and @EXPORT_OK with Exporter.
201              
202              
203             =head1 DEFINING AND INHERITING VARIABLES
204              
205              
206             =head2 Method interface
207              
208             BEGIN {
209             Class->pkg_inheritable('$scalar');
210             Class->pkg_inheritable('@array' => [1,2,3]);
211             Class->pkg_const_inheritable('$const_scalar' => 'readonly');
212             inherit BaseClass;
213             }
214              
215             Every variable declaration must be inside a BEGIN block because there's no 'our'
216             declaration of that variable and we need compile time installation of that
217             symbol in the package symbol table. The same holds for the call to inherit(),
218             inherited variables must be installed at compile time.
219              
220              
221             =head2 Exporter like interface
222              
223             BEGIN {
224             our @EXPORT_INHERIT = qw( $scalar @array );
225             inherit BaseClass;
226             }
227             our $scalar;
228             our @array = (1,2,3);
229              
230             If you're defining variables, none of which is overriding a parent package's one
231             (see overriding below), it's not required to define @EXPORT_INHERIT inside
232             a BEGIN block.
233             You will declare the variables via 'our' in the usual way.
234             The actual our declaration of each variable must be outside the BEGIN block in
235             any case because of 'our' scoping rules.
236              
237              
238             =head1 OVERRIDING VARIABLES
239              
240             In order to override a parent variable you just have to redefine that
241             variable in the current package.
242             When you use the Exporter like interface and you want to override a parent
243             package variable you must define @EXPORT_INHERIT before calling inherit(),
244             otherwise inherit() will not find any of your overrides.
245             On the contrary, if you use the pkg_inheritable() method interface, ordering
246             doesn't matter.
247              
248              
249             =head1 METHODS
250              
251             =head2 inherit
252              
253             Make the caller package inherit variables from the package on which the method is invoked.
254             e.g.
255              
256             package Derived;
257             BEGIN {
258             inherit Base;
259             # or
260             Base->inherit;
261             }
262              
263             will make Derived inherit variables from Base.
264              
265             This method must be invoked from within a BEGIN block in order to
266             install the inherited variables at compile time.
267             Otherwise any attempt to refer to those package variables in your code will
268             trigger a 'Global symbol "$yourvar" requires explicit package name' error.
269              
270             =cut
271              
272              
273             =head2 pkg_inheritable
274              
275             Class->pkg_inheritable('$variable_name');
276             Class->pkg_inheritable('$variable_name' => $value);
277             Class->pkg_inheritable('@variable_name' => ['value1','value2']);
278              
279             Method interface to declare/override an inheritable package variable.
280             $variable_name will be installed in the package symbol table like it had
281             been declared with use 'vars' and then initialized.
282             The variable will be inherited by packages invoking inherit() on class 'Class'.
283              
284             =head2 pkg_const_inheritable
285              
286             Class->pkg_const_inheritable('$variable_name');
287             Class->pkg_const_inheritable('$variable_name' => $value);
288             Class->pkg_const_inheritable('@variable_name' => ['value1','value2']);
289              
290             Method interface to declare/override an inheritable constant package variable.
291             It is similar to pkg_inheritable but the variable will be made constant. Only
292             constant scalars are supported.
293             It's possible to override a parent package var that was constant and make it
294             non constant, as well as the opposite.
295              
296             =cut
297              
298             =head1 EXAMPLES
299              
300             =head2 Inheriting and overriding
301              
302             # set up Base class with the method interface:
303             use strict;
304             package Base;
305             use base qw( Package::Data::Inheritable );
306            
307             BEGIN {
308             Base->pkg_inheritable('$scalar1' => 'Base scalar');
309             Base->pkg_inheritable('$scalar2' => 'Base scalar');
310             Base->pkg_inheritable('@array' => [1,2,3]);
311             }
312            
313             print $scalar1; # prints "Base scalar"
314             print @array; # prints 123
315            
316             # set up Derived class with the Exporter like interface:
317             package Derived;
318             use base qw( Base );
319            
320             BEGIN {
321             # declare our variables and overrides *before* inheriting
322             our @EXPORT_INHERIT = qw( $scalar2 @array );
323            
324             inherit Base;
325             }
326             our @array = (2,4,6);
327             our $scalar2 = "Derived scalar";
328            
329             print $scalar2; # prints "Derived scalar"
330             print $Base::scalar2; # prints "Base scalar"
331             print @array; # prints 246
332             print $scalar1; # prints "Base scalar"
333              
334             $scalar1 = "Base and Derived scalar";
335             print $Base::scalar1, # prints "Base and Derived scalar" twice
336             $Derived::scalar1;
337              
338              
339             =head2 Accessing and wrapping data members
340              
341             Be aware that when you qualify your variables with the package prefix you're
342             giving up compiler checks on those variables. In any case, direct access to
343             class data from outside your classes is better avoided.
344              
345             use strict;
346             package Base;
347             use base qw( Package::Data::Inheritable );
348              
349             BEGIN {
350             Base->pkg_inheritable('$_some_scalar' => 'some scalar');
351             Base->pkg_inheritable('$public_scalar' => 'public scalar');
352             }
353              
354             sub new { bless {}, shift }
355              
356             # accessor/mutator example
357             sub some_scalar {
358             my $class = shift;
359             if (@_) {
360             my $val = shift;
361             # check $val, caller etc. or croak...
362             $_some_scalar = $val;
363             }
364             return $_some_scalar;
365             }
366              
367             sub do_something {
368             my ($self) = @_;
369             print $public_scalar; # ok
370             print $Base::public_scalar; # ok, but dangerous
371              
372             print $publicscalar; # compile error
373              
374             print $Base::publicscalar; # variable undefined but no compile
375             # error because of package prefix
376             }
377              
378             package Derived;
379             use base qw( Base );
380             BEGIN {
381             inherit Base;
382             }
383            
384             And then in some user code:
385              
386             use strict;
387             use Base;
388             use Derived;
389            
390             print $Base::public_scalar; # prints "public scalar". Discouraged.
391             print Base->some_scalar; # prints "some scalar"
392            
393             Base->some_scalar("reset!");
394             my $obj = Base->new;
395             print Base->some_scalar; # prints "reset!"
396             print $obj->some_scalar; # prints "reset!"
397             print Derived->some_scalar; # prints "reset!"
398              
399             Derived->some_scalar("derived reset!");
400             print Derived->some_scalar; # prints "derived reset!"
401             print Base->some_scalar; # prints "derived reset!"
402              
403              
404             =head1 CAVEATS
405              
406             The interface of this module is not stable yet.
407             I'm still looking for ways to reduce the amount of boilerplate code needed.
408             Suggestions and comments are welcome.
409              
410              
411             =head1 AUTHOR
412              
413             Giacomo Cerrai, C<< >>
414              
415             =head1 BUGS
416              
417             Please report any bugs or feature requests to
418             C, or through the web interface at
419             L.
420             I will be notified, and then you'll automatically be notified of progress on
421             your bug as I make changes.
422              
423             =head1 SUPPORT
424              
425             You can find documentation for this module with the perldoc command.
426              
427             perldoc Package::Data::Inheritable
428              
429             You can also look for information at:
430              
431             =over 4
432              
433             =item * AnnoCPAN: Annotated CPAN documentation
434              
435             L
436              
437             =item * CPAN Ratings
438              
439             L
440              
441             =item * RT: CPAN's request tracker
442              
443             L
444              
445             =item * Search CPAN
446              
447             L
448              
449             =back
450              
451             =head1 SEE ALSO
452              
453             Class::Data::Inheritable,
454              
455             =head1 ACKNOWLEDGEMENTS
456              
457             =head1 COPYRIGHT & LICENSE
458              
459             Copyright 2007 Giacomo Cerrai, all rights reserved.
460              
461             This program is free software; you can redistribute it and/or modify it
462             under the same terms as Perl itself.
463              
464             =cut
465              
466             ######################################################
467             # TECHNICALITIES
468             #
469             # - OVERRIDING VARIABLES
470             # When you use the Exporter like interface and you want to override a parent
471             # package variable you must define @EXPORT_INHERIT before calling inherit(),
472             # otherwise inherit() will not find any of your overrides.
473             # On the contrary, if you use the pkg_inheritable() method interface, ordering
474             # doesn't matter. If you define your overrides before calling inherit,
475             # @EXPORT_INHERIT will already be defined (being set by the method calls).
476             # If you call inherit and after that you call pkg_inheritable(), this will take
477             # care of performing the overriding. Do not fit well in the POD but they're still useful
478              
479             1; # End of Package::Data::Inheritable