File Coverage

blib/lib/Class/Virtually/Abstract.pm
Criterion Covered Total %
statement 48 71 67.6
branch 8 26 30.7
condition 3 3 100.0
subroutine 11 13 84.6
pod 1 1 100.0
total 71 114 62.2


line stmt bran cond sub pod time code
1             package Class::Virtually::Abstract;
2              
3 2     2   33364 use strict;
  2         5  
  2         58  
4 2     2   9 use warnings;
  2         3  
  2         75  
5 2     2   9 use vars qw(%Registered $VERSION @ISA);
  2         4  
  2         192  
6              
7             require Class::Virtual;
8             @ISA = qw(Class::Virtual);
9             $VERSION = '0.08';
10              
11             {
12 2     2   7 no strict 'refs';
  2         2  
  2         310  
13              
14             sub virtual_methods {
15 16     16 1 1622 my($base_class) = shift;
16              
17 16 100 100     59 if( @_ and !$Registered{$base_class} ) {
18 5         7 $Registered{$base_class} = 1;
19              
20 5         7 my($has_orig_import) = 0;
21              
22 5 100       5 if( defined &{$base_class.'::import'} ) {
  5         34  
23             # Divert the existing import method.
24 1         1 $has_orig_import = 1;
25 1         1 *{$base_class.'::__orig_import'} = \&{$base_class.'::import'};
  1         5  
  1         4  
26             }
27              
28             # We can't use a closure here, SUPER wouldn't work right. :(
29 2 0   2   12 eval <<"IMPORT";
  2 0   1   3  
  2 0   1   316  
  1 50   1   4  
  1 50   0   1  
  1 50   1   123  
  1 50   1   3  
  1 0   0   2  
  1 0       113  
  1 0       4  
  1 0       1  
  1         117  
  5         401  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  1         27  
  1         3  
  1         5  
  1         3  
  0         0  
  0         0  
  1         1  
  1         3  
  1         555  
  1         3  
  1         3  
  1         3  
  1         4  
  1         164  
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
30             package $base_class;
31              
32             no warnings 'redefine';
33              
34             sub import {
35             my \$class = shift;
36             return if \$class eq '$base_class';
37              
38             my \@missing_methods = \$class->missing_methods;
39             if (\@missing_methods) {
40             require Carp;
41             Carp::croak("Class \$class must define ".
42             join(', ', \@missing_methods).
43             " for class $base_class");
44             }
45              
46             # Since import() is typically caller() sensitive, these
47             # must be gotos.
48             if( $has_orig_import ) {
49             goto &${base_class}::__orig_import;
50             }
51             elsif( my \$super_import = \$class->can('SUPER::import') ) {
52             goto &\$super_import;
53             }
54             }
55             IMPORT
56              
57             }
58              
59 16         53 $base_class->SUPER::virtual_methods(@_);
60             }
61             }
62              
63             1;
64              
65              
66             =pod
67              
68             =head1 NAME
69              
70             Class::Virtually::Abstract - Compile-time enforcement of Class::Virtual
71              
72              
73             =head1 SYNOPSIS
74              
75             package My::Virtual::Idaho;
76             use base qw(Class::Virtually::Abstract);
77              
78             __PACKAGE__->virtual_methods(qw(new foo bar this that));
79              
80              
81             package My::Private::Idaho;
82             use base qw(My::Virtual::Idaho);
83              
84             sub new { ... }
85             sub foo { ... }
86             sub bar { ... }
87             sub this { ... }
88             # oops, forgot to implement that()!! Whatever will happen?!
89              
90              
91             # Meanwhile, in another piece of code!
92             # KA-BLAM! My::Private::Idaho fails to compile because it didn't
93             # fully implement My::Virtual::Idaho.
94             use My::Private::Idaho;
95              
96             =head1 DESCRIPTION
97              
98             This subclass of Class::Virtual provides B enforcement.
99             That means subclasses of your virtual class are B to
100             implement all virtual methods or else it will not compile.
101              
102              
103             =head1 BUGS and CAVEATS
104              
105             Because this relies on import() it is important that your classes are
106             Bd instead of Bd. This is a problem, and I'm trying to
107             figure a way around it.
108              
109             Also, if a subclass defines its own import() routine (I've done it)
110             Class::Virtually::Abstract's compile-time checking is defeated.
111              
112             Got to think of a better way to do this besides import().
113              
114              
115             =head1 AUTHOR
116              
117             Original idea and code from Ben Tilly's AbstractClass
118             http://www.perlmonks.org/index.pl?node_id=44300&lastnode_id=45341
119              
120             Embraced and Extended by Michael G Schwern Eschwern@pobox.comE
121              
122              
123             =head1 SEE ALSO
124              
125             L
126              
127             =cut
128              
129             1;