File Coverage

blib/lib/Class/MakeMethods/Standard/Inheritable.pm
Criterion Covered Total %
statement 49 76 64.4
branch 21 48 43.7
condition 3 11 27.2
subroutine 8 11 72.7
pod 4 4 100.0
total 85 150 56.6


line stmt bran cond sub pod time code
1             =head1 NAME
2              
3             Class::MakeMethods::Standard::Inheritable - Overridable data
4              
5             =head1 SYNOPSIS
6              
7             package MyClass;
8              
9             use Class::MakeMethods( 'Standard::Inheritable:scalar' => 'foo' );
10             # We now have an accessor method for an "inheritable" scalar value
11            
12             MyClass->foo( 'Foozle' ); # Set a class-wide value
13             print MyClass->foo(); # Retrieve class-wide value
14            
15             my $obj = MyClass->new(...);
16             print $obj->foo(); # All instances "inherit" that value...
17            
18             $obj->foo( 'Foible' ); # until you set a value for an instance.
19             print $obj->foo(); # This now finds object-specific value.
20             ...
21            
22             package MySubClass;
23             @ISA = 'MyClass';
24            
25             print MySubClass->foo(); # Intially same as superclass,
26             MySubClass->foo('Foobar'); # but overridable per subclass,
27             print $subclass_obj->foo(); # and shared by its instances
28             $subclass_obj->foo('Fosil');# until you override them...
29             ...
30            
31             # Similar behaviour for hashes and arrays is currently incomplete
32             package MyClass;
33             use Class::MakeMethods::Standard::Inheritable (
34             array => 'my_list',
35             hash => 'my_index',
36             );
37            
38             MyClass->my_list(0 => 'Foozle', 1 => 'Bang!');
39             print MyClass->my_list(1);
40            
41             MyClass->my_index('broccoli' => 'Blah!', 'foo' => 'Fiddle');
42             print MyClass->my_index('foo');
43              
44              
45             =head1 DESCRIPTION
46              
47             The MakeMethods subclass provides accessor methods that search an inheritance tree to find a value. This allows you to set a shared or default value for a given class, optionally override it in a subclass, and then optionally override it on a per-instance basis.
48              
49             Note that all MakeMethods methods are inheritable, in the sense that they work as expected for subclasses. These methods are different in that the I accessed by each method can be inherited or overridden in each subclass or instance. See L< Class::MakeMethods::Utility::Inheritable> for more about this type of "inheritable" or overridable" data.
50              
51              
52             =head2 Calling Conventions
53              
54             When you C this package, the method names you provide
55             as arguments cause subroutines to be generated and installed in
56             your module.
57              
58             See L for more information.
59              
60             =head2 Declaration Syntax
61              
62             To declare methods, pass in pairs of a method-type name followed
63             by one or more method names.
64              
65             Valid method-type names for this package are listed in L<"METHOD
66             GENERATOR TYPES">.
67              
68             See L and L for more information.
69              
70             =cut
71              
72             package Class::MakeMethods::Standard::Inheritable;
73              
74             $VERSION = 1.000;
75 2     2   16378 use strict;
  2         5  
  2         70  
76              
77 2     2   1317 use Class::MakeMethods::Standard '-isasubclass';
  2         5  
  2         21  
78 2     2   1531 use Class::MakeMethods::Utility::Inheritable qw(get_vvalue set_vvalue find_vself);
  2         5  
  2         14  
79 2     2   1366 use Class::MakeMethods::Utility::ArraySplicer 'array_splicer';
  2         6  
  2         13  
80              
81             ########################################################################
82              
83             =head1 METHOD GENERATOR TYPES
84              
85             =head2 scalar - Class-specific Accessor
86              
87             For each method name passed, uses a closure to generate a subroutine with the following characteristics:
88              
89             =over 4
90              
91             =item *
92              
93             May be called as a class or instance method, on the declaring class or any subclass.
94              
95             =item *
96              
97             If called without any arguments returns the current value for the callee. If the callee has not had a value defined for this method, searches up from instance to class, and from class to superclass, until a callee with a value is located.
98              
99             =item *
100              
101             If called with an argument, stores that as the value associated with the callee, whether instance or class, and returns it,
102              
103             =back
104              
105             Sample declaration and usage:
106              
107             package MyClass;
108             use Class::MakeMethods::Standard::Inheritable (
109             scalar => 'foo',
110             );
111             ...
112            
113             # Store value
114             MyClass->foo('Foozle');
115            
116             # Retrieve value
117             print MyClass->foo;
118              
119             =cut
120              
121             sub scalar {
122 2     2 1 6 my $class = shift;
123 3         7 map {
124 2         14 my $method = $_;
125 3         6 my $name = $method->{name};
126 3   50     34 $method->{data} ||= {};
127             $name => sub {
128 18     18   243 my $self = shift;
129 18 100       39 if ( scalar(@_) == 0 ) {
130 14         47 get_vvalue($method->{data}, $self);
131             } else {
132 4         6 my $value = shift;
133 4         15 set_vvalue($method->{data}, $self, $value);
134             }
135             }
136 3         22 } $class->_get_declarations(@_)
137             }
138              
139             ########################################################################
140              
141             =head2 array - Class-specific Ref Accessor
142              
143             For each method name passed, uses a closure to generate a subroutine with the following characteristics:
144              
145             =over 4
146              
147             =item *
148              
149             May be called as a class method, or on any instance or subclass, Must be called on a hash-based instance.
150              
151             =item *
152              
153             The class value will be a reference to an array (or undef).
154              
155             =item *
156              
157             If called without any arguments, returns the contents of the array in list context, or an array reference in scalar context (or undef).
158              
159             =item *
160              
161             If called with a single array ref argument, sets the contents of the array to match the contents of the provided one.
162              
163             =item *
164              
165             If called with a single numeric argument, uses that argument as an index to retrieve from the referenced array, and returns that value (or undef).
166              
167             =item *
168              
169             If called with a two arguments, the first undefined and the second an array ref argument, uses that array's contents as a list of indexes to return a slice of the referenced array.
170              
171             =item *
172              
173             If called with a list of argument pairs, each with a non-ref index and an associated value, stores the value at the given index in the referenced array. If the class value was previously undefined, a new array is autovivified. The current value in each position will be overwritten, and later arguments with the same index will override earlier ones. Returns the current array-ref value.
174              
175             =item *
176              
177             If called with a list of argument pairs, each with the first item being a reference to an array of up to two numbers, loops over each pair and uses those numbers to splice the value array.
178              
179             The first controlling number is the position at which the splice will begin. Zero will start before the first item in the list. Negative numbers count backwards from the end of the array.
180              
181             The second number is the number of items to be removed from the list. If it is omitted, or undefined, or zero, no items are removed. If it is a positive integer, that many items will be returned.
182              
183             If both numbers are omitted, or are both undefined, they default to containing the entire value array.
184              
185             If the second argument is undef, no values will be inserted; if it is a non-reference value, that one value will be inserted; if it is an array-ref, its values will be copied.
186              
187             The method returns the items that removed from the array, if any.
188              
189             =back
190              
191             Sample declaration and usage:
192            
193             package MyClass;
194             use Class::MakeMethods::Standard::Inheritable (
195             array => 'bar',
196             );
197             ...
198            
199             # Clear and set contents of list
200             print MyClass->bar([ 'Spume', 'Frost' ] );
201            
202             # Set values by position
203             MyClass->bar(0 => 'Foozle', 1 => 'Bang!');
204            
205             # Positions may be overwritten, and in any order
206             MyClass->bar(2 => 'And Mash', 1 => 'Blah!');
207            
208             # Retrieve value by position
209             print MyClass->bar(1);
210            
211             # Direct access to referenced array
212             print scalar @{ MyClass->bar() };
213              
214             There are also calling conventions for slice and splice operations:
215              
216             # Retrieve slice of values by position
217             print join(', ', MyClass->bar( undef, [0, 2] ) );
218            
219             # Insert an item at position in the array
220             MyClass->bar([3], 'Potatoes' );
221            
222             # Remove 1 item from position 3 in the array
223             MyClass->bar([3, 1], undef );
224            
225             # Set a new value at position 2, and return the old value
226             print MyClass->bar([2, 1], 'Froth' );
227              
228             =cut
229              
230             sub array {
231 0     0 1 0 my $class = shift;
232 0         0 map {
233 0         0 my $method = $_;
234 0         0 my $name = $method->{name};
235             $name => sub {
236 0     0   0 my $self = shift;
237              
238 0 0 0     0 if ( scalar(@_) == 0 ) {
    0          
239 0         0 my $v_self = find_vself($method->{data}, $self);
240 0 0       0 my $value = $v_self ? $method->{data}{$v_self} : ();
241 0 0 0     0 if ( $method->{auto_init} and ! $value ) {
242 0         0 $value = $method->{data}{$self} = [];
243             }
244 0 0       0 ! $value ? () : wantarray ? @$value : $value;
    0          
245            
246             } elsif ( scalar(@_) == 1 and ref $_[0] eq 'ARRAY' ) {
247 0         0 $method->{data}{$self} = [ @{ $_[0] } ];
  0         0  
248 0 0       0 wantarray ? @{ $method->{data}{$self} } : $method->{data}{$self}
  0         0  
249            
250             } else {
251 0 0       0 if ( ! exists $method->{data}{$self} ) {
252 0         0 my $v_self = find_vself($method->{data}, $self);
253 0 0       0 $method->{data}{$self} = [ $v_self ? @$v_self : () ];
254             }
255 0         0 return array_splicer( $method->{data}{$self}, @_ );
256             }
257             }
258 0         0 } $class->_get_declarations(@_)
259             }
260              
261             ########################################################################
262              
263             =head2 hash - Class-specific Ref Accessor
264              
265             For each method name passed, uses a closure to generate a subroutine with the following characteristics:
266              
267             =over 4
268              
269             =item *
270              
271             May be called as a class method, or on any instance or subclass, Must be called on a hash-based instance.
272              
273             =item *
274              
275             The class value will be a reference to a hash (or undef).
276              
277             =item *
278              
279             If called without any arguments, returns the contents of the hash in list context, or a hash reference in scalar context. If the callee has not had a value defined for this method, searches up from instance to class, and from class to superclass, until a callee with a value is located.
280              
281             =item *
282              
283             If called with one non-ref argument, uses that argument as an index to retrieve from the referenced hash, and returns that value (or undef). If the callee has not had a value defined for this method, searches up from instance to class, and from class to superclass, until a callee with a value is located.
284              
285             =item *
286              
287             If called with one array-ref argument, uses the contents of that array to retrieve a slice of the referenced hash. If the callee has not had a value defined for this method, searches up from instance to class, and from class to superclass, until a callee with a value is located.
288              
289             =item *
290              
291             If called with one hash-ref argument, sets the contents of the referenced hash to match that provided.
292              
293             =item *
294              
295             If called with a list of key-value pairs, stores the value under the given key in the hash associated with the callee, whether instance or class. If the callee did not previously have a hash-ref value associated with it, searches up instance to class, and from class to superclass, until a callee with a value is located, and copies that hash before making the assignments. The current value under each key will be overwritten, and later arguments with the same key will override earlier ones. Returns the contents of the hash in list context, or a hash reference in scalar context.
296              
297             =back
298              
299             Sample declaration and usage:
300              
301             package MyClass;
302             use Class::MakeMethods::Standard::Inheritable (
303             hash => 'baz',
304             );
305             ...
306            
307             # Set values by key
308             MyClass->baz('foo' => 'Foozle', 'bar' => 'Bang!');
309            
310             # Values may be overwritten, and in any order
311             MyClass->baz('broccoli' => 'Blah!', 'foo' => 'Fiddle');
312            
313             # Retrieve value by key
314             print MyClass->baz('foo');
315            
316             # Retrive slice of values by position
317             print join(', ', MyClass->baz( ['foo', 'bar'] ) );
318            
319             # Direct access to referenced hash
320             print keys %{ MyClass->baz() };
321            
322             # Reset the hash contents to empty
323             @{ MyClass->baz() } = ();
324              
325             B
326              
327             =cut
328              
329             sub hash {
330 1     1 1 2 my $class = shift;
331 2         3 map {
332 1         7 my $method = $_;
333 2         4 my $name = $method->{name};
334             $name => sub {
335 17     17   2806 my $self = shift;
336 17 100       75 if ( scalar(@_) == 0 ) {
    100          
    50          
337 9         44 my $v_self = find_vself($method->{data}, $self);
338 9 100       29 my $value = $v_self ? $method->{data}{$v_self} : ();
339 9 100 66     61 if ( $method->{auto_init} and ! $value ) {
340 3         12 $value = $method->{data}{$self} = {};
341             }
342 9 50       82 ! $value ? () : wantarray ? %$value : $value;
    50          
343             } elsif ( scalar(@_) == 1 ) {
344 4 50       15 if ( ref($_[0]) eq 'HASH' ) {
    100          
345 0         0 $method->{data}{$self} = { %{$_[0]} };
  0         0  
346             } elsif ( ref($_[0]) eq 'ARRAY' ) {
347 1         5 my $v_self = find_vself($method->{data}, $self);
348 1 50       4 return unless $v_self;
349 1         2 return @{$method->{data}{$v_self}}{ @{$_[0]} }
  1         5  
  1         3  
350             } else {
351 3         14 my $v_self = find_vself($method->{data}, $self);
352 3 100       13 return unless $v_self;
353 2         12 return $method->{data}{$v_self}->{ $_[0] };
354             }
355             } elsif ( scalar(@_) % 2 ) {
356 0         0 Carp::croak "Odd number of items in assigment to $method->{name}";
357             } else {
358 4 50       17 if ( ! exists $method->{data}{$self} ) {
359 0         0 my $v_self = find_vself($method->{data}, $self);
360 0 0       0 $method->{data}{$self} = { $v_self ? %$v_self : () };
361             }
362 4         12 while ( scalar(@_) ) {
363 6         11 my $key = shift();
364 6         29 $method->{data}{$self}->{ $key } = shift();
365             }
366 4 50       25 wantarray ? %{ $method->{data}{$self} } : $method->{data}{$self};
  0            
367             }
368             }
369 2         19 } $class->_get_declarations(@_)
370             }
371              
372             ########################################################################
373              
374             =head2 object - Class-specific Ref Accessor
375              
376             For each method name passed, uses a closure to generate a subroutine with the following characteristics:
377              
378             =over 4
379              
380             =item *
381              
382             May be called as a class method, or on any instance or subclass, Must be called on a hash-based instance.
383              
384             =item *
385              
386             The class value will be a reference to an object (or undef).
387              
388             =item *
389              
390             If called without any arguments returns the current value for the callee. If the callee has not had a value defined for this method, searches up from instance to class, and from class to superclass, until a callee with a value is located.
391              
392             =item *
393              
394             If called with an argument, stores that as the value associated with the callee, whether instance or class, and returns it,
395              
396             =back
397              
398             Sample declaration and usage:
399              
400             package MyClass;
401             use Class::MakeMethods::Standard::Inheritable (
402             object => 'foo',
403             );
404             ...
405            
406             # Store value
407             MyClass->foo( Foozle->new() );
408            
409             # Retrieve value
410             print MyClass->foo;
411              
412             B
413              
414             =cut
415              
416 0     0 1   sub object { }
417              
418             ########################################################################
419              
420             =head1 SEE ALSO
421              
422             See L for general information about this distribution.
423              
424             See L for more about this family of subclasses.
425              
426             =cut
427              
428             1;