line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
#!/usr/local/bin/perl
|
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
=head1 NAME
|
4
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
Class::Structured - provides a more structured class system for Perl
|
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
=head1 DESCRIPTION
|
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
Specifically, this function provides for variables with access specifiers
|
10
|
|
|
|
|
|
|
that will inherit properly, for constructors, and for abstract functions.
|
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
Abstract functions may be used on their own with no performance penalty.
|
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
Constructors and access specified variables each imply the use of the other -
|
15
|
|
|
|
|
|
|
and will incur a semi-significant performance penalty.
|
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
Also, note that when using all of the features it can cause problems to define
|
18
|
|
|
|
|
|
|
an AUTOLOAD function - so please don't.
|
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
=head1 HISTORY
|
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
=over 2
|
23
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
=item *
|
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
02/04/02 - Robby Walker - released - version 0.1
|
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
=item *
|
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
12/10/01 - Robby Walker - added private variable support, tested - version 0.003
|
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
=item *
|
33
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
12/06/01 - Robby Walker - adding abstract listing, checking and constructors - version 0.002
|
35
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
=item *
|
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
12/05/01 - Robby Walker - created the file, wrote abstract support - version 0.001
|
39
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
=back
|
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
=head1 METHODS
|
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
=over 4
|
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
=cut
|
47
|
|
|
|
|
|
|
#----------------------------------------------------------
|
48
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
package Class::Structured;
|
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
# MODULE METADATA
|
52
|
|
|
|
|
|
|
our $VERSION = 0.1;
|
53
|
|
|
|
|
|
|
our @ISA = qw(Exporter);
|
54
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
our @EXPORT = ();
|
56
|
|
|
|
|
|
|
our @EXPORT_OK = qw(declare_abstract implementation constructor default_constructor define_variables);
|
57
|
|
|
|
|
|
|
our %EXPORT_TAGS = (
|
58
|
|
|
|
|
|
|
all => [qw(declare_abstract implementation constructor default_constructor define_variables)]
|
59
|
|
|
|
|
|
|
);
|
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
# PRAGMATIC DEPENDENCIES
|
62
|
1
|
|
|
1
|
|
108958
|
use strict "vars";
|
|
1
|
|
|
|
|
4
|
|
|
1
|
|
|
|
|
40
|
|
63
|
1
|
|
|
1
|
|
5
|
use strict "subs";
|
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
24
|
|
64
|
1
|
|
|
1
|
|
5
|
use warnings;
|
|
1
|
|
|
|
|
6
|
|
|
1
|
|
|
|
|
31
|
|
65
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
# OUTSIDE DEPENDENCIES
|
67
|
1
|
|
|
1
|
|
5
|
use Carp;
|
|
1
|
|
|
|
|
8
|
|
|
1
|
|
|
|
|
69
|
|
68
|
1
|
|
|
1
|
|
978
|
use Set::Scalar;
|
|
1
|
|
|
|
|
47263
|
|
|
1
|
|
|
|
|
2247
|
|
69
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
# ========================================================================
|
71
|
|
|
|
|
|
|
# METHODS
|
72
|
|
|
|
|
|
|
# ========================================================================
|
73
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
# ------------------------------------------------------------------------
|
75
|
|
|
|
|
|
|
# Methods for abstract functions
|
76
|
|
|
|
|
|
|
# ------------------------------------------------------------------------
|
77
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
=item declare_abstract
|
79
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
Declares an abstract function in the current package.
|
81
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
=cut
|
83
|
|
|
|
|
|
|
sub declare_abstract {
|
84
|
0
|
|
|
0
|
1
|
|
my $function_name = pop; # get last param as function name
|
85
|
0
|
|
|
|
|
|
my $package = caller;
|
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
# update the abstract list (keep it as a weird name so we don't have a collision with a real variable name)
|
88
|
0
|
|
|
|
|
|
my $list_name = $package.'::'.'!structured!.abstracts';
|
89
|
|
|
|
|
|
|
|
90
|
0
|
0
|
|
|
|
|
${ $list_name } = Set::Scalar->new() unless defined ${ $list_name };
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
91
|
0
|
|
|
|
|
|
${ $list_name }->insert( $function_name );
|
|
0
|
|
|
|
|
|
|
92
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
# declare the function
|
94
|
0
|
|
|
|
|
|
*{ $package.'::'.$function_name } =
|
95
|
|
|
|
|
|
|
sub {
|
96
|
0
|
|
|
0
|
|
|
croak "$function_name in class $package is declared abstract, and cannot be called";
|
97
|
0
|
|
|
|
|
|
};
|
98
|
|
|
|
|
|
|
}
|
99
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
=item list_abstracts
|
101
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
Provides a list of all the abstracts left by a package for subclasses to implement.
|
103
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
=cut
|
105
|
|
|
|
|
|
|
sub list_abstracts {
|
106
|
0
|
|
|
0
|
1
|
|
my $package = shift;
|
107
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
# create a set to list all abstracts
|
109
|
0
|
|
|
|
|
|
my $plist_name = $package.'::!structured!.abstracts';
|
110
|
0
|
|
|
|
|
|
my $list;
|
111
|
|
|
|
|
|
|
|
112
|
|
|
|
|
|
|
# add all locally declared abstracts - as definites
|
113
|
0
|
0
|
|
|
|
|
if ( defined ${ $plist_name } ) {
|
|
0
|
|
|
|
|
|
|
114
|
0
|
|
|
|
|
|
$list = ${ $plist_name }->clone;
|
|
0
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
} else {
|
116
|
0
|
|
|
|
|
|
$list = Set::Scalar->new;
|
117
|
|
|
|
|
|
|
}
|
118
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
# get a set for each parent class's abstracts
|
120
|
0
|
|
|
|
|
|
my %parents;
|
121
|
|
|
|
|
|
|
my $parent;
|
122
|
0
|
|
|
|
|
|
my @parents = @{ $package.'::ISA' };
|
|
0
|
|
|
|
|
|
|
123
|
0
|
|
|
|
|
|
foreach $parent ( @parents ) {
|
124
|
0
|
|
|
|
|
|
my @abstracts = list_abstracts($parent);
|
125
|
|
|
|
|
|
|
|
126
|
0
|
0
|
|
|
|
|
if ( @abstracts + 0 ) {
|
127
|
0
|
|
|
|
|
|
$parents{$parent} = Set::Scalar->new(@abstracts);
|
128
|
|
|
|
|
|
|
}
|
129
|
|
|
|
|
|
|
}
|
130
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
# this variable holds a list of functions we know to be implemented (i.e. not abstract)
|
132
|
0
|
|
|
|
|
|
my $notlist = Set::Scalar->new;
|
133
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
# now, step over each parent, adding abstracts when no other parent implements that function
|
135
|
|
|
|
|
|
|
# note that this code makes no allowance for AUTOLOAD, which is why we state earlier that this
|
136
|
|
|
|
|
|
|
# Perl feature should be avoided when using Class::Structured
|
137
|
0
|
|
|
|
|
|
foreach $parent (keys %parents) {
|
138
|
0
|
|
|
|
|
|
my $function;
|
139
|
0
|
|
|
|
|
|
my @abstracts = $parents{$parent}->members;
|
140
|
|
|
|
|
|
|
|
141
|
0
|
|
|
|
|
|
foreach $function (@abstracts) {
|
142
|
|
|
|
|
|
|
# skip this if we already know the function to be abstract or implemented
|
143
|
0
|
0
|
0
|
|
|
|
next if ($list->member($function) || $notlist->member($function));
|
144
|
|
|
|
|
|
|
|
145
|
0
|
|
|
|
|
|
my $can;
|
146
|
0
|
0
|
|
|
|
|
if ( defined *{ $package.'::'.$function }{CODE} ) {
|
|
0
|
|
|
|
|
|
|
147
|
|
|
|
|
|
|
# does this package override it?
|
148
|
0
|
|
|
|
|
|
$can = 1;
|
149
|
|
|
|
|
|
|
} else {
|
150
|
|
|
|
|
|
|
# does one of this package's parents override it
|
151
|
0
|
|
|
|
|
|
my $other;
|
152
|
0
|
|
|
|
|
|
$can = 0;
|
153
|
0
|
|
|
|
|
|
foreach $other (@parents) {
|
154
|
0
|
0
|
|
|
|
|
next if ($other eq $parent);
|
155
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
# if the parent can run the function, and not just because it
|
157
|
|
|
|
|
|
|
# declares it abstract, mark the function as implemented
|
158
|
0
|
0
|
0
|
|
|
|
if ( !((exists $parents{$other}) && ($parents{$other}->member($function)))
|
|
|
|
0
|
|
|
|
|
159
|
|
|
|
|
|
|
&& $other->can( $function ) )
|
160
|
|
|
|
|
|
|
{
|
161
|
0
|
|
|
|
|
|
$can = 1;
|
162
|
0
|
|
|
|
|
|
last;
|
163
|
|
|
|
|
|
|
}
|
164
|
|
|
|
|
|
|
}
|
165
|
|
|
|
|
|
|
}
|
166
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
# add to the appropriate list
|
168
|
0
|
0
|
|
|
|
|
($can ? $notlist : $list)->insert( $function );
|
169
|
|
|
|
|
|
|
}
|
170
|
|
|
|
|
|
|
}
|
171
|
|
|
|
|
|
|
|
172
|
0
|
|
|
|
|
|
my @members = $list->members;
|
173
|
0
|
|
|
|
|
|
return @members;
|
174
|
|
|
|
|
|
|
}
|
175
|
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
=item check_abstracts
|
177
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
When instantiating a class, make sure that it has declared all the necessary abstracts
|
179
|
|
|
|
|
|
|
|
180
|
|
|
|
|
|
|
=cut
|
181
|
|
|
|
|
|
|
sub check_abstracts {
|
182
|
0
|
|
|
0
|
1
|
|
my $package = shift;
|
183
|
|
|
|
|
|
|
|
184
|
|
|
|
|
|
|
# if we have no abstracts, we are OK
|
185
|
0
|
|
|
|
|
|
return ! ( list_abstracts($package) + 0 );
|
186
|
|
|
|
|
|
|
}
|
187
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
# ------------------------------------------------------------------------
|
189
|
|
|
|
|
|
|
# Constructor related functions
|
190
|
|
|
|
|
|
|
# ------------------------------------------------------------------------
|
191
|
|
|
|
|
|
|
|
192
|
|
|
|
|
|
|
=item constructor
|
193
|
|
|
|
|
|
|
|
194
|
|
|
|
|
|
|
Creates a new constructor.
|
195
|
|
|
|
|
|
|
|
196
|
|
|
|
|
|
|
=cut
|
197
|
|
|
|
|
|
|
sub constructor {
|
198
|
0
|
|
|
0
|
1
|
|
my $name = shift;
|
199
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
# load parameters, doing some aerobics to ensure their proper loading
|
201
|
0
|
|
0
|
0
|
|
|
my $code = pop || sub {};
|
|
0
|
|
|
|
|
|
|
202
|
0
|
0
|
|
|
|
|
my %supers = %{ pop || {} };
|
|
0
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
|
204
|
|
|
|
|
|
|
# determine what package we are making a constructor for
|
205
|
0
|
|
|
|
|
|
my $package = caller;
|
206
|
0
|
0
|
|
|
|
|
if ( $package eq 'Class::Structured' ) {
|
207
|
|
|
|
|
|
|
# if our caller is just 'default_constructor', find our true caller
|
208
|
0
|
|
|
|
|
|
($package) = caller(1);
|
209
|
|
|
|
|
|
|
}
|
210
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
# mark ourself as the default constructor
|
212
|
0
|
|
|
|
|
|
my $varname = $package.'::!structured!.default_constructor';
|
213
|
0
|
0
|
|
|
|
|
${ $varname } = $name unless defined ${ $varname };
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
|
215
|
|
|
|
|
|
|
# iterate through parent classes, using either the specified
|
216
|
|
|
|
|
|
|
# constructor or the default constructor
|
217
|
0
|
|
|
|
|
|
my $parent;
|
218
|
0
|
|
|
|
|
|
my @parents = @{ $package.'::ISA' };
|
|
0
|
|
|
|
|
|
|
219
|
0
|
|
|
|
|
|
foreach $parent ( @parents ) {
|
220
|
|
|
|
|
|
|
# use the specified constructor, if there is one
|
221
|
0
|
0
|
|
|
|
|
next if exists $supers{$parent};
|
222
|
|
|
|
|
|
|
|
223
|
0
|
|
|
|
|
|
my $default = ${ $parent.'::!structured!.default_constructor' };
|
|
0
|
|
|
|
|
|
|
224
|
0
|
0
|
|
|
|
|
$supers{$parent} = $default if defined $default;
|
225
|
|
|
|
|
|
|
}
|
226
|
|
|
|
|
|
|
|
227
|
|
|
|
|
|
|
# now, define the constructor function
|
228
|
0
|
|
|
|
|
|
*{ $package.'::'.$name } =
|
229
|
|
|
|
|
|
|
sub {
|
230
|
0
|
|
|
0
|
|
|
my $type = shift;
|
231
|
0
|
|
|
|
|
|
my $self;
|
232
|
|
|
|
|
|
|
|
233
|
|
|
|
|
|
|
# figure out how we were called
|
234
|
0
|
0
|
|
|
|
|
if ( ref($type) ) {
|
235
|
0
|
|
|
|
|
|
my $reftype = ref($type);
|
236
|
0
|
0
|
|
|
|
|
if ( $reftype eq $package ) {
|
|
|
0
|
|
|
|
|
|
237
|
|
|
|
|
|
|
# called with an instance of our own type
|
238
|
0
|
|
|
|
|
|
croak "Cloning is not yet supported by Class::Structured constructors - sorry!";
|
239
|
|
|
|
|
|
|
} elsif ( $reftype->isa( $package ) ) {
|
240
|
|
|
|
|
|
|
# called from below in the hierarchy
|
241
|
0
|
|
|
|
|
|
$self = $type;
|
242
|
|
|
|
|
|
|
}
|
243
|
|
|
|
|
|
|
} else {
|
244
|
|
|
|
|
|
|
# called as a constructor
|
245
|
0
|
|
|
|
|
|
$self = construct( $type );
|
246
|
|
|
|
|
|
|
}
|
247
|
|
|
|
|
|
|
|
248
|
|
|
|
|
|
|
# call our parent constructors
|
249
|
0
|
|
|
|
|
|
my $parent;
|
250
|
0
|
|
|
|
|
|
foreach $parent ( keys %supers ) {
|
251
|
0
|
|
|
|
|
|
&{ $parent.'::'.$supers{$parent} }( $self, @_ );
|
|
0
|
|
|
|
|
|
|
252
|
|
|
|
|
|
|
}
|
253
|
|
|
|
|
|
|
|
254
|
|
|
|
|
|
|
# call our own constructor
|
255
|
0
|
0
|
|
|
|
|
$code->( $self, @_ ) if $code;
|
256
|
|
|
|
|
|
|
|
257
|
0
|
|
|
|
|
|
$self;
|
258
|
0
|
|
|
|
|
|
};
|
259
|
|
|
|
|
|
|
}
|
260
|
|
|
|
|
|
|
|
261
|
|
|
|
|
|
|
=item default_constructor
|
262
|
|
|
|
|
|
|
|
263
|
|
|
|
|
|
|
Creates a new constructor, and also marks it as the default.
|
264
|
|
|
|
|
|
|
|
265
|
|
|
|
|
|
|
=cut
|
266
|
|
|
|
|
|
|
sub default_constructor {
|
267
|
0
|
|
|
0
|
1
|
|
my $package = caller;
|
268
|
0
|
|
|
|
|
|
${ $package.'::!structured!.default_constructor' } = $_[0];
|
|
0
|
|
|
|
|
|
|
269
|
0
|
|
|
|
|
|
constructor( @_ );
|
270
|
|
|
|
|
|
|
}
|
271
|
|
|
|
|
|
|
|
272
|
|
|
|
|
|
|
=item implementation
|
273
|
|
|
|
|
|
|
|
274
|
|
|
|
|
|
|
Prototyped sub used to generate syntax
|
275
|
|
|
|
|
|
|
|
276
|
|
|
|
|
|
|
=cut
|
277
|
|
|
|
|
|
|
sub implementation (&) {
|
278
|
0
|
|
|
0
|
1
|
|
$_[0];
|
279
|
|
|
|
|
|
|
}
|
280
|
|
|
|
|
|
|
|
281
|
|
|
|
|
|
|
=item construct
|
282
|
|
|
|
|
|
|
|
283
|
|
|
|
|
|
|
Internal function used to set up a class variable.
|
284
|
|
|
|
|
|
|
|
285
|
|
|
|
|
|
|
=cut
|
286
|
|
|
|
|
|
|
sub construct {
|
287
|
0
|
|
|
0
|
1
|
|
my $package = shift;
|
288
|
|
|
|
|
|
|
|
289
|
|
|
|
|
|
|
# check the abstracts
|
290
|
0
|
0
|
|
|
|
|
croak "Class $package has the following undefined abstracts and therefore cannot be created: ".
|
291
|
|
|
|
|
|
|
join ", ", list_abstracts( $package ) unless check_abstracts( $package );
|
292
|
|
|
|
|
|
|
|
293
|
|
|
|
|
|
|
# add the public function, if necessary
|
294
|
0
|
0
|
|
|
|
|
unless ( defined *{ $package.'::public' }{CODE} ) {
|
|
0
|
|
|
|
|
|
|
295
|
0
|
|
|
|
|
|
*{ $package.'::public' } =
|
296
|
|
|
|
|
|
|
sub : lvalue {
|
297
|
0
|
|
|
0
|
|
|
$_[0]->{public}->{$_[1]};
|
298
|
0
|
|
|
|
|
|
};
|
299
|
|
|
|
|
|
|
}
|
300
|
|
|
|
|
|
|
|
301
|
|
|
|
|
|
|
# bless the reference
|
302
|
0
|
|
|
|
|
|
bless {}, $package;
|
303
|
|
|
|
|
|
|
}
|
304
|
|
|
|
|
|
|
|
305
|
|
|
|
|
|
|
# ------------------------------------------------------------------------
|
306
|
|
|
|
|
|
|
# Private and Public Variable Functions
|
307
|
|
|
|
|
|
|
# ------------------------------------------------------------------------
|
308
|
|
|
|
|
|
|
|
309
|
|
|
|
|
|
|
=item define_variables
|
310
|
|
|
|
|
|
|
|
311
|
|
|
|
|
|
|
=cut
|
312
|
|
|
|
|
|
|
sub define_variables {
|
313
|
0
|
|
|
0
|
1
|
|
my %params = @_;
|
314
|
|
|
|
|
|
|
|
315
|
|
|
|
|
|
|
# determine what package we are in
|
316
|
0
|
|
|
|
|
|
my $package = caller;
|
317
|
|
|
|
|
|
|
|
318
|
|
|
|
|
|
|
# iterate over the variables, defining each
|
319
|
0
|
|
|
|
|
|
my $var;
|
320
|
0
|
|
|
|
|
|
foreach $var ( keys %params ) {
|
321
|
|
|
|
|
|
|
# make sure the request is for a private variable
|
322
|
0
|
0
|
|
|
|
|
unless ( lc($params{$var}) eq 'private' ) {
|
323
|
0
|
|
|
|
|
|
carp "$var defined as unsupported type $params{$var}";
|
324
|
0
|
|
|
|
|
|
next;
|
325
|
|
|
|
|
|
|
}
|
326
|
|
|
|
|
|
|
|
327
|
|
|
|
|
|
|
# add to the private variable list
|
328
|
0
|
|
|
|
|
|
my $list_name = $package.'::!structured!.privates';
|
329
|
|
|
|
|
|
|
|
330
|
0
|
0
|
|
|
|
|
${ $list_name } = Set::Scalar->new() unless defined ${ $list_name };
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
331
|
0
|
|
|
|
|
|
${ $list_name }->insert( $var );
|
|
0
|
|
|
|
|
|
|
332
|
|
|
|
|
|
|
|
333
|
|
|
|
|
|
|
# define the access function
|
334
|
0
|
|
|
|
|
|
*{ $package.'::'.$var } =
|
335
|
|
|
|
|
|
|
sub : lvalue {
|
336
|
|
|
|
|
|
|
# get our self
|
337
|
0
|
|
|
0
|
|
|
my $self = shift;
|
338
|
|
|
|
|
|
|
|
339
|
|
|
|
|
|
|
# determine who called us
|
340
|
0
|
|
|
|
|
|
my $caller;
|
341
|
0
|
|
|
|
|
|
my $i = 0;
|
342
|
0
|
|
|
|
|
|
do {
|
343
|
0
|
|
|
|
|
|
($caller) = caller($i++);
|
344
|
|
|
|
|
|
|
} while ($caller eq 'Class::Structured');
|
345
|
|
|
|
|
|
|
|
346
|
0
|
|
|
|
|
|
my $list_name = $caller.'::!structured!.privates';
|
347
|
0
|
0
|
0
|
|
|
|
unless ( ($caller eq $package) ||
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
348
|
|
|
|
|
|
|
( $package->isa( $caller ) && defined($$list_name) && $$list_name->member($var) )) {
|
349
|
|
|
|
|
|
|
# if the caller is not us our a superclass of us making a legitimate inquiry, die
|
350
|
0
|
|
|
|
|
|
croak "Invalid attempt to access variable $var in class $package from $caller";
|
351
|
|
|
|
|
|
|
}
|
352
|
|
|
|
|
|
|
|
353
|
0
|
|
|
|
|
|
$self->{$caller}->{$var};
|
354
|
0
|
|
|
|
|
|
};
|
355
|
|
|
|
|
|
|
}
|
356
|
|
|
|
|
|
|
|
357
|
|
|
|
|
|
|
}
|
358
|
|
|
|
|
|
|
|
359
|
|
|
|
|
|
|
1;
|
360
|
|
|
|
|
|
|
|
361
|
|
|
|
|
|
|
__END__
|