File Coverage

blib/lib/Class/MakeMethods/Utility/Inheritable.pm
Criterion Covered Total %
statement 29 29 100.0
branch 9 10 90.0
condition 2 3 66.6
subroutine 6 6 100.0
pod 3 3 100.0
total 49 51 96.0


line stmt bran cond sub pod time code
1             =head1 NAME
2              
3             Class::MakeMethods::Utility::Inheritable - "Inheritable" data
4              
5              
6             =head1 SYNOPSIS
7              
8             package MyClass;
9             sub new { ... }
10            
11             package MySubclass;
12             @ISA = 'MyClass';
13             ...
14             my $obj = MyClass->new(...);
15             my $subobj = MySubclass->new(...);
16            
17             use Class::MakeMethods::Utility::Inheritable qw(get_vvalue set_vvalue );
18            
19             my $dataset = {};
20             set_vvalue($dataset, 'MyClass', 'Foobar'); # Set value for class
21             get_vvalue($dataset, 'MyClass'); # Gets value "Foobar"
22            
23             get_vvalue($dataset, $obj); # Objects "inherit"
24             set_vvalue($dataset, $obj, 'Foible'); # Until you override
25             get_vvalue($dataset, $obj); # Now finds "Foible"
26            
27             get_vvalue($dataset, 'MySubclass'); # Subclass "inherits"
28             get_vvalue($dataset, $subobj); # As do its objects
29             set_vvalue($dataset, 'MySubclass', 'Foozle'); # Until we override it
30             get_vvalue($dataset, 'MySubclass'); # Now finds "Foozle"
31            
32             get_vvalue($dataset, $subobj); # Change cascades down
33             set_vvalue($dataset, $subobj, 'Foolish'); # Until we override again
34            
35             get_vvalue($dataset, 'MyClass'); # Superclass is unchanged
36              
37             =head1 DESCRIPTION
38              
39             This module provides several functions which allow you to store values in a hash corresponding to both objects and classes, and to retrieve those values by searching a object's inheritance tree until it finds a matching entry.
40              
41             This functionality is used by Class::MakeMethods::Standard::Inheritable and Class::MakeMethods::Composite::Inheritable to construct methods that can both store class data and be overriden on a per-object level.
42              
43             =cut
44              
45             ########################################################################
46              
47             package Class::MakeMethods::Utility::Inheritable;
48              
49             $VERSION = 1.000;
50              
51             @EXPORT_OK = qw( get_vvalue set_vvalue find_vself );
52 9 50   9   5138 sub import { require Exporter and goto &Exporter::import } # lazy Exporter
53              
54 9     9   7071 use strict;
  9         17  
  9         988  
55              
56             ########################################################################
57              
58             =head1 REFERENCE
59              
60             =head2 find_vself
61              
62             $vself = find_vself( $dataset, $instance );
63              
64             Searches $instance's inheritance tree until it finds a matching entry in the dataset, and returns either the instance, the class that matched, or undef.
65              
66             =cut
67              
68             sub find_vself {
69 72     72 1 90 my $dataset = shift;
70 72         82 my $instance = shift;
71              
72 72 100       299 return $instance if ( exists $dataset->{$instance} );
73            
74 41         49 my $v_self;
75 41   66     167 my @isa_search = ( ref($instance) || $instance );
76 41         105 while ( scalar @isa_search ) {
77 49         87 $v_self = shift @isa_search;
78 49 100       221 return $v_self if ( exists $dataset->{$v_self} );
79 9     9   58 no strict 'refs';
  9         15  
  9         1860  
80 23         34 unshift @isa_search, @{"$v_self\::ISA"};
  23         155  
81             }
82 15         49 return;
83             }
84              
85             =head2 get_vvalue
86              
87             $value = get_vvalue( $dataset, $instance );
88              
89             Searches $instance's inheritance tree until it finds a matching entry in the dataset, and returns that value
90              
91             =cut
92              
93             sub get_vvalue {
94 49     49 1 750 my $dataset = shift;
95 49         60 my $instance = shift;
96 49         95 my $v_self = find_vself($dataset, $instance);
97             # warn "Dataset: " . join( ', ', %$dataset );
98             # warn "Retrieving $dataset -> $instance ($v_self): '$dataset->{$v_self}'";
99 49 100       292 return $v_self ? $dataset->{$v_self} : ();
100             }
101              
102             =head2 set_vvalue
103              
104             $value = set_vvalue( $dataset, $instance, $value );
105              
106             Searches $instance's inheritance tree until it finds a matching entry in the dataset, and returns that value
107              
108             =cut
109              
110             sub set_vvalue {
111 15     15 1 44 my $dataset = shift;
112 15         18 my $instance = shift;
113 15         18 my $value = shift;
114 15 100       37 if ( defined $value ) {
115             # warn "Setting $dataset -> $instance = $value";
116 13         58 $dataset->{$instance} = $value;
117             } else {
118             # warn "Clearing $dataset -> $instance";
119 2         7 delete $dataset->{$instance};
120 2         8 undef;
121             }
122             }
123              
124             ########################################################################
125              
126             1;