line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
|
2
|
|
|
|
|
|
|
package Class::Interfaces; |
3
|
|
|
|
|
|
|
|
4
|
1
|
|
|
1
|
|
1279
|
use strict; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
46
|
|
5
|
1
|
|
|
1
|
|
6
|
use warnings; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
411
|
|
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
our $VERSION = '0.04'; |
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
sub import { |
10
|
11
|
|
|
11
|
|
16444
|
my $class = shift; |
11
|
11
|
|
|
|
|
138
|
my %interfaces = @_; |
12
|
11
|
|
|
|
|
33
|
foreach my $interface (keys %interfaces) { |
13
|
|
|
|
|
|
|
# build the interface |
14
|
16
|
|
|
|
|
25
|
my (@methods, @subclasses); |
15
|
16
|
100
|
|
|
|
70
|
if (ref($interfaces{$interface}) eq 'HASH') { |
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
16
|
5
|
|
|
|
|
9
|
my $interface_spec = $interfaces{$interface}; |
17
|
|
|
|
|
|
|
# if we have an isa |
18
|
5
|
100
|
|
|
|
7
|
if (exists ${$interface_spec}{isa}) { |
|
5
|
|
|
|
|
15
|
|
19
|
|
|
|
|
|
|
# if is an array (multiple inheritance) |
20
|
3
|
100
|
|
|
|
11
|
if (ref($interface_spec->{isa}) eq 'ARRAY') { |
21
|
1
|
|
|
|
|
1
|
@subclasses = @{$interface_spec->{isa}}; |
|
1
|
|
|
|
|
4
|
|
22
|
|
|
|
|
|
|
} |
23
|
|
|
|
|
|
|
else { |
24
|
|
|
|
|
|
|
# if its another kind of ref, its an error |
25
|
2
|
100
|
|
|
|
11
|
(!ref($interface_spec->{isa})) |
26
|
|
|
|
|
|
|
|| $class->_error_handler("Interface ($interface) isa list must be an array reference"); |
27
|
|
|
|
|
|
|
# otherwise its just a single item |
28
|
1
|
|
|
|
|
4
|
@subclasses = $interface_spec->{isa}; |
29
|
|
|
|
|
|
|
} |
30
|
|
|
|
|
|
|
} |
31
|
4
|
100
|
|
|
|
6
|
if (exists ${$interface_spec}{methods}) { |
|
4
|
|
|
|
|
13
|
|
32
|
3
|
100
|
|
|
|
18
|
(ref($interface_spec->{methods}) eq 'ARRAY') |
33
|
|
|
|
|
|
|
|| $class->_error_handler("Method list for Interface ($interface) must be an array reference"); |
34
|
2
|
|
|
|
|
3
|
@methods = @{$interface_spec->{methods}}; |
|
2
|
|
|
|
|
6
|
|
35
|
|
|
|
|
|
|
} |
36
|
|
|
|
|
|
|
} |
37
|
|
|
|
|
|
|
elsif (ref($interfaces{$interface}) eq 'ARRAY') { |
38
|
9
|
|
|
|
|
11
|
@methods = @{$interfaces{$interface}}; |
|
9
|
|
|
|
|
26
|
|
39
|
|
|
|
|
|
|
} |
40
|
|
|
|
|
|
|
elsif (!defined($interfaces{$interface})) { |
41
|
|
|
|
|
|
|
# allow undefined here, this indicates an empty |
42
|
|
|
|
|
|
|
# interface, sometimes called a marker interface |
43
|
|
|
|
|
|
|
; |
44
|
|
|
|
|
|
|
} |
45
|
|
|
|
|
|
|
else { |
46
|
1
|
|
|
|
|
8
|
$class->_error_handler("Cannot use a " . $interfaces{$interface} . " to build an interface"); |
47
|
|
|
|
|
|
|
} |
48
|
|
|
|
|
|
|
# now create the interfaces |
49
|
13
|
|
|
|
|
43
|
my $package = $class->_build_interface_package($interface, @subclasses); |
50
|
13
|
|
|
1
|
|
566
|
eval $package; |
|
1
|
|
|
|
|
1921
|
|
51
|
13
|
100
|
|
|
|
52
|
$class->_error_handler("Could not create Interface ($interface) because", $@) if $@; |
52
|
11
|
|
|
|
|
16
|
eval { |
53
|
11
|
|
|
|
|
71
|
my $method_stub = $class->can('_method_stub'); |
54
|
1
|
|
|
1
|
|
23
|
no strict 'refs'; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
394
|
|
55
|
|
|
|
|
|
|
# without at least this VERSION declaration |
56
|
|
|
|
|
|
|
# a Marker interface will not work with |
57
|
|
|
|
|
|
|
# 'use base' basically it would complain |
58
|
|
|
|
|
|
|
# that the package is empty. |
59
|
|
|
|
|
|
|
# we only assign this if the VERSION is already |
60
|
|
|
|
|
|
|
# empty too, so we don't step on any customizations |
61
|
|
|
|
|
|
|
# done in subclasses. |
62
|
11
|
|
50
|
|
|
15
|
${"${interface}::"}{VERSION} ||= -1; |
|
11
|
|
|
|
|
61
|
|
63
|
|
|
|
|
|
|
# now we create all our methods :) |
64
|
11
|
|
|
|
|
23
|
foreach my $method (@methods) { |
65
|
12
|
100
|
|
|
|
47
|
($method !~ /^(BEGIN|INIT|CHECK|END|DESTORY|AUTOLOAD|import|bootstrap)$/) |
66
|
|
|
|
|
|
|
|| $class->_error_handler("Cannot create an interface using reserved perl methods"); |
67
|
11
|
|
|
|
|
11
|
*{"${interface}::${method}"} = $method_stub; |
|
11
|
|
|
|
|
76
|
|
68
|
|
|
|
|
|
|
} |
69
|
|
|
|
|
|
|
}; |
70
|
11
|
100
|
|
|
|
147
|
$class->_error_handler("Could not create sub methods for Interface ($interface) because", $@) if $@; |
71
|
|
|
|
|
|
|
} |
72
|
|
|
|
|
|
|
} |
73
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
sub _build_interface_package { |
75
|
13
|
|
|
13
|
|
30
|
my ($class, $interface, @subclasses) = @_; |
76
|
13
|
|
|
|
|
29
|
my $package = "package $interface;"; |
77
|
13
|
100
|
|
|
|
39
|
$package .= "\@${interface}::ISA = qw(" . (join " " => @subclasses) . ");" if @subclasses; |
78
|
13
|
|
|
|
|
31
|
return $package; |
79
|
|
|
|
|
|
|
} |
80
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
sub _error_handler { |
82
|
6
|
|
|
6
|
|
12
|
my ($class, $message, $sub_exception) = @_; |
83
|
6
|
100
|
|
|
|
28
|
die "$message : $sub_exception" if $sub_exception; |
84
|
4
|
|
|
|
|
52
|
die "$message"; |
85
|
|
|
|
|
|
|
} |
86
|
|
|
|
|
|
|
|
87
|
3
|
|
|
3
|
|
1682
|
sub _method_stub { die "Method Not Implemented" } |
88
|
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
1; |
90
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
__END__ |