File Coverage

blib/lib/Class/Class.pm
Criterion Covered Total %
statement 165 177 93.2
branch 74 94 78.7
condition 14 47 29.7
subroutine 36 37 97.3
pod 2 7 28.5
total 291 362 80.3


line stmt bran cond sub pod time code
1             package Class::Class;
2              
3             require 5.005;
4             require Pragmatic;
5              
6 5     5   70436 use strict;
  5         12  
  5         920  
7              
8              
9             %Class::Class::BUILT_METHODS = ( );
10              
11             @Class::Class::EXPORT_OK = qw (package_exists);
12              
13             @Class::Class::ISA = qw(Pragmatic);
14              
15             # Bookkeepping; use our own MEMBERS so that objects inherit this,
16             # instead of it being global:
17             %Class::Class::MEMBERS =
18             (__inited => '%',
19             __tried_polymorph => '%');
20              
21             %Class::Class::PRAGMATA =
22             (override_inherited =>
23             sub { $Class::Class::OVERRIDE_INHERITED = 1; });
24              
25             # The package version, both in 1.23 style *and* usable by MakeMaker:
26             $Class::Class::VERSION = (substr q$Revision: 1.18 $, 10) - 1;
27             my $rcs = ' $Id: Class.pm,v 1.18 2000/01/05 16:15:48 binkley Exp $ ' ;
28              
29              
30 5     5   32 use Carp ( );
  5         19  
  5         110  
31 5     5   4841 use Class::ISA;
  5         17746  
  5         152  
32 5     5   4947 use Symbol ( );
  5         6151  
  5         191  
33              
34              
35 5     5   149 BEGIN { $Class::Class::OVERRIDE_INHERITED = 0; }
36              
37              
38             # Yes, it's true: I provide a default "new" for you. See the
39             # documentation (below) for an explanation of this so-called feature.
40             sub new ($;@) {
41             # Why is this here?? --bko FIXME
42 5     5   30 no strict qw(refs);
  5         11  
  5         850  
43              
44 4     4 0 2519 my ($this, @args) = @_;
45 4   33     35 my $class = ref ($this) || $this;
46 4         12 my $self = { };
47 4         11 bless $self, $class;
48              
49 4         37 $self->renew (@args);
50             }
51              
52             # This is used to reinitialize objects:
53             sub renew ($;@) {
54 6     6 0 15 my ($self, @args) = @_;
55              
56 6         50 return $self->_make_methods->_process_args (@args)->_initialize_parents;
57             }
58              
59             # Copy an object:
60             sub clone ($;@) {
61 0     0 0 0 my ($self, @args) = @_;
62              
63 0         0 return $self->new ($self, @args);
64             }
65              
66             # NOT a method:
67             sub package_exists ($) {
68 5     5   30 no strict qw (refs);
  5         7  
  5         695  
69              
70 14     14 0 23 my ($class) = @_;
71 14         22 $class =~ s/^:://o; # catch ::TopLevelPackage
72             # Start at the root stash:
73 14         20 my $last = '::';
74              
75             # Look in each successive sub-stash: [NB - the RE there just keeps
76             # the :: tacked onto the end of the preceding package label: a
77             # zero-width positive lookbehind assertion :-]
78 14         87 for (split /(?<=::)/o, "$class\::") {
79 20 100       24 return undef unless exists ${$last}{$_};
  20         158  
80 10         21 $last = $_;
81             }
82              
83 4         69 return 1;
84             }
85              
86             # NB -- This is not (presently) a supported method for Class::Class --
87             # as a matter of fact, I consider it quite broken. Why is it here?
88             # Since Class::Class has such intimate knowlege of your classes
89             # inheritance tree, it was easy for me to implement object changing
90             # into other objects, a feature I use in a seperate dynamic
91             # web-content system. If I get request to support this, I may fix
92             # "polymorph" properly: until then, caveat emptor. Double extra so
93             # for polyvolve!
94              
95             # Turn into a different class:
96             sub polymorph ($;$@) {
97 5     5   29 no strict qw(refs);
  5         8  
  5         1785  
98              
99 8     8 1 103 my ($self, $class, @args) = @_;
100              
101             # Catch ::TopLevelModule:
102 8         23 $class =~ s/^:://o;
103              
104             # Safe to call with no arguments:
105 8 50       21 return $self unless $class;
106              
107             # We've already initialized (I think... ? --bko FIXME), so just
108             # upcast ourselves:
109 8 100 66     91 return bless $self, $class
110             if ($self->isa ($class) or $self->__tried_polymorph ($class));
111              
112             # Save time and effort for next time through (note, we cache this
113             # even for non-existent classes, just to save the work):
114 7         30 $self->__tried_polymorph ($class, 1);
115              
116 7         22 (my $file = $class) =~ s,::,/,go;
117 7         14 $file .= '.pm';
118              
119             # Limit the scope of the __DIE__ handler by using a block:
120             {
121             # Watch out that someone else may have installed a handler ahead
122             # of us:
123 7         10 local $SIG{__DIE__} = sub {
124 7 50   7   183 die $_[0] unless $_[0] =~ /^Can't locate $file in \@INC/;
125 7         73 };
126              
127             # Since use must have a bareword, carry out it's operations
128             # explicitly rather than fall back on eval "use $class". This
129             # avoids the overhead of recompiling the string each time:
130 7         14 eval { require $file; };
  7         3061  
131              
132             # Try to setup the class anyway, in case it's defined not in
133             # it's own separate file, but watch out -- it is just fine to
134             # have no import method defined; need to be very careful not to
135             # artificially create a stash for the package where none existed
136             # before:
137 7 100 66     29 $class->import
138             if (package_exists ($class) and $class->can ('import'));
139             }
140              
141 7 100       88 return $self unless package_exists ($class);
142              
143 2         6 bless $self, $class;
144              
145 2         19 return $self->renew (@args);
146             }
147              
148             # This is like polymorph, except that I keep trying until it works,
149             # stripping off the last ::package name from the target class. Again,
150             # I use this for a dynamic-content web system. It could go there, but
151             # this functionality has nothing to do with web pages. An example to
152             # illustrate: turn a Fred into a Human::Caveman::Flintstone::Barney,
153             # else a Human::Caveman::Flintstone, else a Human::Caveman, else a
154             # Human, else return the original Fred.
155              
156             sub polyvolve ($;$@) {
157 2     2 1 18 my ($self, $class, @args) = @_;
158              
159 2   100     4 do {
160 5         18 $self = $self->polymorph ($class, @args);
161             } while ($class ne ref $self and $class =~ s/::[^:]+$//o);
162              
163 2         6 return $self;
164             }
165              
166             # Yes, it's true: I provide a default DESTROY for you. See the
167             # documentation (below) for an explanation of this so-called feature.
168             sub DESTROY ($) {
169 5     5   30 no strict qw(refs);
  5         7  
  5         3045  
170              
171 2     2   165 my ($self) = @_;
172 2         5 my $class = ref $self;
173              
174             # Give ourselves a chance to call cleanup code:
175 2         2 my $glob = ${"$class\::"}{uninitialize};
  2         6  
176             # This is for the object's package itself defining the method:
177 2 50 33     10 $self->unitialize if (defined $glob and defined *{$glob}{CODE});
  0         0  
178              
179 2         3 for (keys %{"$class\::MEMBERS"}) {
  2         11  
180             # Use internal knowlege. This needs fixing for array
181             # representation:
182 14 100       47 $self->{$_} = undef if exists $self->{$_};
183             }
184              
185 2         5 for my $class (@{"$class\::ISA"}) {
  2         5  
186             # Explicity run super DESTROYS so we can handle multiple
187             # inheritance:
188 2         5 bless $self, $class;
189 2         132 $self->DESTROY;
190             }
191              
192             # Make us ourselves again so that we don't try to run more super's
193             # DESTROYS:
194 0         0 bless $self, $class;
195             }
196              
197             ### Methods below here are for implementation only -- need to look
198             ### into using arrays instead of hashes:
199              
200             sub add_method ($$$) {
201 5     5   41 no strict qw(refs);
  5         11  
  5         10512  
202              
203 33     33 0 74 my ($this, $name, $type) = @_;
204             # Allowed to call as Fred::Barney->add_method (...):
205 33   33     133 my $class = ref ($this) || $this;
206 33         39 my $glob = ${"$class\::"}{$name};
  33         82  
207              
208 33 100       163 if ($type eq '$') { # scalar
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
209 14         79 *{"$class\::$name"} = sub ($;$) {
210 33 100   33   782 (scalar @_ == 2) ? ($_[0]->{$name} = $_[1])
211             : ($_[0]->{$name});
212 14         59 };
213              
214             } elsif ($type eq '\$') { # scalar reference
215 1         2 *{"$class\::$name"} = sub ($;$) {
216 1 50   1   7 (scalar @_ == 2) ? \($_[0]->{$name} = $_[1])
217             : \($_[0]->{$name});
218 1         4 };
219              
220             } elsif ($type eq '@') { # array
221 1         2 *{"$class\::$name"} = sub ($;$$) {
222 2 50 0 2   11 (scalar @_ == 3) ? ($_[0]->{$name}[$_[1]] = $_[2])
    100          
223             : (scalar @_ == 2) ? ($_[0]->{$name}[$_[1]])
224             : ($_[0]->{$name} ||= [ ]);
225 1         6 };
226              
227             } elsif ($type eq '\@') { # array reference
228 1         2 *{"$class\::$name"} = sub ($;$$) {
229 2 50 0 2   13 (scalar @_ == 3) ? \($_[0]->{$name}[$_[1]] = $_[2])
    100          
230             : (scalar @_ == 2) ? \($_[0]->{$name}[$_[1]])
231             : ($_[0]->{$name} ||= [ ]);
232 1         4 };
233              
234             } elsif ($type eq '%') { # hash
235 9         63 *{"$class\::$name"} = sub ($;$$) {
236 63 50 0 63   394 (scalar @_ == 3) ? ($_[0]->{$name}{$_[1]} = $_[2])
    100          
237             : (scalar @_ == 2) ? ($_[0]->{$name}{$_[1]})
238             : ($_[0]->{$name} ||= { });
239 9         34 };
240              
241             } elsif ($type eq '\%') { # hash reference
242 1         3 *{"$class\::$name"} = sub ($;$$) {
243 2 50 0 2   369 (scalar @_ == 3) ? \($_[0]->{$name}{$_[1]} = $_[2])
    100          
244             : (scalar @_ == 2) ? \($_[0]->{$name}{$_[1]})
245             : ($_[0]->{$name} ||= { });
246 1         3 };
247              
248             } elsif ($type eq '*') { # glob
249 1         3 *{"$class\::$name"} = sub ($;$) {
250 0         0 (scalar @_ == 2) ? ($_[0]->{$name} = $_[1])
251 1 50 0 1   28 : ($_[0]->{$name} ||= *{Symbol::gensym ( )});
252 1         3 };
253              
254             } elsif ($type eq '\*') { # glob reference
255 1         3 *{"$class\::$name"} = sub ($;$) {
256 0         0 (scalar @_ == 2) ? \($_[0]->{$name} = $_[1])
257 1 50 0 1   9 : \($_[0]->{$name} ||= *{Symbol::gensym ( )});
258 1         8 };
259              
260             } elsif ($type eq '&') { # coderef
261 1         2 *{"$class\::$name"} = sub ($;$) {
262             # Surpress subroutine redefined and prototype mismatch:
263 1     1   6 local $^W = 0;
264             local $SIG{__WARN__} = sub {
265 1 50       17 warn @_ unless $_[0] =~ /^Prototype mismatch:/o;
266 1         7 };
267 1 50       3 (scalar @_ == 2) ? (*{"$class\::$name"} = $_[1])
  1         18  
268             : Carp::croak ("No coderef defined for '$name' yet");
269 1         4 };
270              
271             } elsif ($type eq '\&') { # coderef reference
272 1         4 *{"$class\::$name"} = sub ($;$) {
273 2     2   179 my ($self, $value) = @_; # need lexicals
274             (scalar @_ == 2) ? ($self->{$name} = $value)
275             # Need to do it this way so that we can arrange for $self to
276             # be at the front of the argument list, as if by magic:
277 2 100   1   14 : (sub { $self->{$name}->($self, @_); });
  1         3  
278 1         4 };
279              
280             } elsif ($type =~ /^[^\\]/) { # class (we hope)
281 1         4 *{"$class\::$name"} = sub ($;$) {
282 1 50 33 1   98 Carp::croak ("Not a class or subclass of '$_[1]'")
283             if defined $_[1] and not UNIVERSAL::isa ($_[1], $type);
284              
285             # Be super careful -- because of closure tricks, need to use
286             # $type->new syntax instead of new $type. (Why? See TC's
287             # "indirect object syntax considered harmful" whitepaper.)
288 1 50 33     39 (scalar @_ == 2) ? ($_[0]->{$name} = $_[1])
289             : ($_[0]->{$name} ||= $type->new);
290 1         10 };
291              
292             } else { # class reference (we hope)
293 1         4 $type =~ s/^\\//o; # object class is name sans leader
294              
295 1         3 *{"$class\::$name"} = sub ($;$) {
296 1 50 33 1   124 Carp::croak ("Not a class or subclass of '$_[1]'")
297             if defined $_[1] and not UNIVERSAL::isa ($_[1], $type);
298              
299             # Be super careful -- because of closure tricks, need to use
300             # $type->new syntax instead of new $type. (Why? See TC's
301             # "indirect object syntax considered harmful" whitepaper.)
302 1 50 33     29 (scalar @_ == 2) ? \($_[0]->{$name} = $_[1])
303             : \($_[0]->{$name} ||= $type->new);
304 1         8 };
305             }
306              
307 33         110 return $this;
308             }
309              
310             sub _make_methods ($) {
311 5     5   47 no strict qw(refs);
  5         14  
  5         3870  
312              
313 6     6   14 my ($self) = @_;
314              
315             # Build from most derived to least derived order:
316 6         39 foreach my $class (Class::ISA::self_and_super_path (ref $self)) {
317             # Try to avoid fooling around with a parent class which defines
318             # MEMBERS but for different purposes:
319 43 100       791 next unless UNIVERSAL::isa ($class, __PACKAGE__);
320              
321             # Check the cache so we don't do this twice:
322 31 100       88 next if $Class::Class::BUILT_METHODS{$class};
323              
324 21         31 for my $key (keys %{"$class\::MEMBERS"}) {
  21         101  
325             # Careful not to override user-defined access methods:
326 33 50       69 if ($Class::Class::OVERRIDE_INHERITED) {
327             # This is for the object's package itself defining the method:
328 0         0 my $glob = ${"$class\::"}{$key};
  0         0  
329 0 0 0     0 next if (defined $glob and defined *{$glob}{CODE});
  0         0  
330              
331             } else {
332             # This is for inherited methods:
333 33 50       485 next if $self->can ($key);
334             }
335              
336 33         47 $class->add_method ($key, ${"$class\::MEMBERS"}{$key});
  33         208  
337             }
338              
339 21         56 $Class::Class::BUILT_METHODS{$class} = 1;
340             }
341              
342             # Lastly, wire in our DESTROY:
343 6         21 my $class = ref $self;
344 6         14 *{"$class\::DESTROY"} = \&DESTROY;
  6         30  
345              
346 6         70 return $self;
347             };
348              
349             sub _process_args ($;@) {
350 6     6   11 my $self = shift; # important not to use my ($self) = @_;
351 6         10 my @args;
352              
353 6         27 while (ref $_[0]) {
354 0         0 push @args, %{(shift)};
  0         0  
355             }
356              
357             # Include yourself so you don't delete existing keys:
358 6         83 %$self = (%$self, @args, @_);
359              
360 6         53 return $self;
361             }
362              
363             sub _initialize_parents ($) {
364 5     5   37 no strict qw(refs);
  5         6  
  5         1266  
365              
366 26     26   47 my ($self) = @_;
367             # To restore my class after initing my parents:
368 26         42 my $class = ref $self;
369              
370             # Initing is idempotent:
371 26 100       136 return $self if $self->__inited ($class);
372             # I'm not inited until after all my parents init, but this breaks
373             # downcasting via polymorph. Think about this more. --bko FIXME
374 21         61 $self->__inited ($class, 1);
375              
376 21         25 for (@{"$class\::ISA"}) {
  21         73  
377 24 100       120 next unless UNIVERSAL::isa ($_, __PACKAGE__);
378              
379             # While initializing, self should be the class of the parent so
380             # that ISA lookup doesn't check unconstructed subclasses:
381 20         181 $self = (bless $self, $_)->_initialize_parents;
382             }
383              
384             # Check if we've been polymorphed into a subclass already:
385 21 100       120 bless $self, $class unless UNIVERSAL::isa (ref $self, $class);
386              
387 13         54 $self = &{"$class\::initialize"} ($self)
  21         108  
388 21 100       27 if defined &{"$class\::initialize"};
389              
390 21         89 return $self;
391             }
392              
393             1;
394              
395              
396             __END__