line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Object::Tiny; |
2
|
|
|
|
|
|
|
|
3
|
3
|
|
|
3
|
|
3587
|
use strict 'vars', 'subs'; |
|
3
|
|
|
|
|
6
|
|
|
3
|
|
|
|
|
130
|
|
4
|
|
|
|
|
|
|
BEGIN { |
5
|
3
|
|
|
3
|
|
73
|
require 5.004; |
6
|
3
|
|
|
|
|
746
|
$Object::Tiny::VERSION = '1.08'; |
7
|
|
|
|
|
|
|
} |
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
sub import { |
10
|
3
|
50
|
|
3
|
|
488
|
return unless shift eq 'Object::Tiny'; |
11
|
3
|
|
|
|
|
5
|
my $pkg = caller; |
12
|
3
|
|
|
|
|
5
|
my $child = !! @{"${pkg}::ISA"}; |
|
3
|
|
|
|
|
16
|
|
13
|
5
|
100
|
33
|
|
|
64
|
eval join "\n", |
|
|
|
66
|
|
|
|
|
14
|
|
|
|
|
|
|
"package $pkg;", |
15
|
|
|
|
|
|
|
($child ? () : "\@${pkg}::ISA = 'Object::Tiny';"), |
16
|
|
|
|
|
|
|
map { |
17
|
3
|
50
|
|
2
|
|
12
|
defined and ! ref and /^[^\W\d]\w*\z/s |
|
2
|
|
|
2
|
|
12
|
|
|
2
|
|
|
|
|
4959
|
|
18
|
|
|
|
|
|
|
or die "Invalid accessor name '$_'"; |
19
|
4
|
|
|
|
|
194
|
"sub $_ { return \$_[0]->{$_} }" |
20
|
|
|
|
|
|
|
} @_; |
21
|
2
|
50
|
|
|
|
8
|
die "Failed to generate $pkg" if $@; |
22
|
2
|
|
|
|
|
27
|
return 1; |
23
|
|
|
|
|
|
|
} |
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
sub new { |
26
|
2
|
|
|
2
|
0
|
2000
|
my $class = shift; |
27
|
2
|
|
|
|
|
9
|
bless { @_ }, $class; |
28
|
|
|
|
|
|
|
} |
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
1; |
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
__END__ |
33
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
=pod |
35
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
=head1 NAME |
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
Object::Tiny - Class building as simple as it gets |
39
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
=head1 SYNOPSIS |
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
# Define a class |
43
|
|
|
|
|
|
|
package Foo; |
44
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
use Object::Tiny qw{ bar baz }; |
46
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
1; |
48
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
# Use the class |
51
|
|
|
|
|
|
|
my $object = Foo->new( bar => 1 ); |
52
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
print "bar is " . $object->bar . "\n"; |
54
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
=head1 DESCRIPTION |
56
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
There's a whole bunch of class builders out there. In fact, creating |
58
|
|
|
|
|
|
|
a class builder seems to be something of a rite of passage (this is |
59
|
|
|
|
|
|
|
my fifth, at least). |
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
Unfortunately, most of the time I want a class builder I'm in a |
62
|
|
|
|
|
|
|
hurry and sketching out lots of fairly simple data classes with fairly |
63
|
|
|
|
|
|
|
simple structure, mostly just read-only accessors, and that's about it. |
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
Often this is for code that won't end up on CPAN, so adding a small |
66
|
|
|
|
|
|
|
dependency doesn't matter much. I just want to be able to define these |
67
|
|
|
|
|
|
|
classes FAST. |
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
By which I mean LESS typing than writing them by hand, not more. And |
70
|
|
|
|
|
|
|
I don't need all those weird complex features that bloat out the code |
71
|
|
|
|
|
|
|
and take over the whole way I build modules. |
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
And so, I present yet another member of the Tiny family of modules, |
74
|
|
|
|
|
|
|
Object::Tiny. |
75
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
The goal here is really just to save me some typing. There's others |
77
|
|
|
|
|
|
|
that could do the job just fine, but I want something that does as little |
78
|
|
|
|
|
|
|
as possible and creates code the same way I'd have written it by hand |
79
|
|
|
|
|
|
|
anyway. |
80
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
To use Object::Tiny, just call it with a list of accessors to be created. |
82
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
use Object::Tiny 'foo', 'bar'; |
84
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
For a large list, I lay it out like this... |
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
use Object::Tiny qw{ |
88
|
|
|
|
|
|
|
item_font_face |
89
|
|
|
|
|
|
|
item_font_color |
90
|
|
|
|
|
|
|
item_font_size |
91
|
|
|
|
|
|
|
item_text_content |
92
|
|
|
|
|
|
|
item_display_time |
93
|
|
|
|
|
|
|
seperator_font_face |
94
|
|
|
|
|
|
|
seperator_font_color |
95
|
|
|
|
|
|
|
seperator_font_size |
96
|
|
|
|
|
|
|
seperator_text_content |
97
|
|
|
|
|
|
|
}; |
98
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
This will create a bunch of simple accessors, and set the inheritance to |
100
|
|
|
|
|
|
|
be the child of Object::Tiny. |
101
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
Object::Tiny is empty other than a basic C<new> constructor which |
103
|
|
|
|
|
|
|
does the following |
104
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
sub new { |
106
|
|
|
|
|
|
|
my $class = shift; |
107
|
|
|
|
|
|
|
return bless { @_ }, $class; |
108
|
|
|
|
|
|
|
} |
109
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
In fact, if doing the following in your class gets annoying... |
111
|
|
|
|
|
|
|
|
112
|
|
|
|
|
|
|
sub new { |
113
|
|
|
|
|
|
|
my $class = shift; |
114
|
|
|
|
|
|
|
my $self = $class->SUPER::new( @_ ); |
115
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
# Extra checking and such |
117
|
|
|
|
|
|
|
... |
118
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
return $self; |
120
|
|
|
|
|
|
|
} |
121
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
... then feel free to ditch the SUPER call and just create the hash |
123
|
|
|
|
|
|
|
yourself! It's not going to make a lick of different and there's nothing |
124
|
|
|
|
|
|
|
magic going on under the covers you might break. |
125
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
And that's really all there is to it. Let a million simple data classes |
127
|
|
|
|
|
|
|
bloom. Features? We don't need no stinking features. |
128
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
=head2 Handling Subclasses |
130
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
If the class you are using Object::Tiny for is already a subclass of |
132
|
|
|
|
|
|
|
another Object::Tiny class (or a subclass of anything else) it doesn't |
133
|
|
|
|
|
|
|
really work to make the class use multiple inheritance. |
134
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
So in this case, Object::Tiny will create the accessors you specify, but |
136
|
|
|
|
|
|
|
WON'T make it a subclass of Object::Tiny. |
137
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
=head2 Why bother when Class::Accessor::* already does the same thing? |
139
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
As a class builder, L<Object::Tiny> inevitably is compared to |
141
|
|
|
|
|
|
|
L<Class::Accessor> and related modules. They seem so similar, so why would |
142
|
|
|
|
|
|
|
I reimplement it? |
143
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
The answer is that for experienced developers that don't need or want |
145
|
|
|
|
|
|
|
hand-holding, Object::Tiny is just outright better, faster or cheaper |
146
|
|
|
|
|
|
|
on every single metric than L<Class::Accessor::Fast>, which |
147
|
|
|
|
|
|
|
is the most comparable member of the Class::Accessor::* family. |
148
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
B<Object::Tiny is 93% smaller than Class::Accessor::Fast> |
150
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
L<Class::Accessor::Fast> requires about 125k of memory to load. |
152
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
Object::Tiny requires about 8k of memory to load. |
154
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
B<Object::Tiny is 75% more terse to use than Class::Accessor::Fast> |
156
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
Object::Tiny is used with the least possible number of keystrokes |
158
|
|
|
|
|
|
|
(short of making the actual name Object::Tiny smaller). |
159
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
And it requires no ugly constructor methods. |
161
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
I mean really, what sort of a method name is 'mk_ro_accessors'. That sort |
163
|
|
|
|
|
|
|
of thing went out of style in the early nineties. |
164
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
Using Class::Accessor::Fast... |
166
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
package Foo::Bar; |
168
|
|
|
|
|
|
|
use base 'Class::Accessor::Fast'; |
169
|
|
|
|
|
|
|
Foo::Bar->mk_ro_accessors(qw{ foo bar baz }); |
170
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
Using Object::Tiny... |
172
|
|
|
|
|
|
|
|
173
|
|
|
|
|
|
|
package Foo::Bar; |
174
|
|
|
|
|
|
|
use Object::Tiny qw{ foo bar baz }; |
175
|
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
Further, Object::Tiny lets you pass your params in directly, without |
177
|
|
|
|
|
|
|
having to wrap them in an additional HASH reference that will just be |
178
|
|
|
|
|
|
|
copied ANYWAY inside the constructor. |
179
|
|
|
|
|
|
|
|
180
|
|
|
|
|
|
|
Using Class::Accessor::Fast... |
181
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
my $object = Foo::Bar->new( { |
183
|
|
|
|
|
|
|
foo => 1, |
184
|
|
|
|
|
|
|
bar => 2, |
185
|
|
|
|
|
|
|
baz => 3, |
186
|
|
|
|
|
|
|
} ); |
187
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
Using Object::Tiny... |
189
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
my $object = Foo::Bar->new( |
191
|
|
|
|
|
|
|
foo => 1, |
192
|
|
|
|
|
|
|
bar => 2, |
193
|
|
|
|
|
|
|
baz => 3, |
194
|
|
|
|
|
|
|
); |
195
|
|
|
|
|
|
|
|
196
|
|
|
|
|
|
|
B<Object::Tiny constructors are 110% faster than Class::Accessor::Fast> |
197
|
|
|
|
|
|
|
|
198
|
|
|
|
|
|
|
Object::Tiny accessors are identical in speed to Class::Accessor::Fast |
199
|
|
|
|
|
|
|
accessors, but Object::Tiny constructors are TWICE as fast as |
200
|
|
|
|
|
|
|
Class::Accessor::Fast constructors, DESPITE C:A:Fast forcing you to pass |
201
|
|
|
|
|
|
|
by reference (which is typically done for speed reasons). |
202
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
Benchmarking constructor plus accessors... |
204
|
|
|
|
|
|
|
Rate accessor tiny |
205
|
|
|
|
|
|
|
accessor 100949/s -- -45% |
206
|
|
|
|
|
|
|
tiny 182382/s 81% -- |
207
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
Benchmarking constructor alone... |
209
|
|
|
|
|
|
|
Rate accessor tiny |
210
|
|
|
|
|
|
|
accessor 156470/s -- -54% |
211
|
|
|
|
|
|
|
tiny 342231/s 119% -- |
212
|
|
|
|
|
|
|
|
213
|
|
|
|
|
|
|
Benchmarking accessors alone... |
214
|
|
|
|
|
|
|
Rate tiny accessor |
215
|
|
|
|
|
|
|
tiny 81.0/s -- -0% |
216
|
|
|
|
|
|
|
accessor 81.0/s 0% -- |
217
|
|
|
|
|
|
|
|
218
|
|
|
|
|
|
|
B<Object::Tiny pollutes your API 95% less than Class::Accessor::Fast> |
219
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
Object::Tiny adds two methods to your class, C<new> and C<import>. The |
221
|
|
|
|
|
|
|
C<new> constructor is so trivial you can just ignore it and use your own |
222
|
|
|
|
|
|
|
if you wish, and the C<import> will shortcut and do nothing (it is used to |
223
|
|
|
|
|
|
|
implement the C<"use Object::Tiny qw{ foo bar baz };"> syntax itself). |
224
|
|
|
|
|
|
|
|
225
|
|
|
|
|
|
|
So if you make your own import, you can ignore the Object::Tiny one. |
226
|
|
|
|
|
|
|
|
227
|
|
|
|
|
|
|
Class::Accessor::Fast isn't quite as light, adding all sorts of useless |
228
|
|
|
|
|
|
|
extra public methods (why on earth would you want to add method accessors |
229
|
|
|
|
|
|
|
at run-time?). |
230
|
|
|
|
|
|
|
|
231
|
|
|
|
|
|
|
Here's what the classes used in the benchmark end up like. |
232
|
|
|
|
|
|
|
|
233
|
|
|
|
|
|
|
DB<1> use Class::Inspector |
234
|
|
|
|
|
|
|
|
235
|
|
|
|
|
|
|
DB<2> x Class::Inspector->methods('Foo_Bar_Tiny'); |
236
|
|
|
|
|
|
|
0 ARRAY(0xfda780) |
237
|
|
|
|
|
|
|
0 'bar' |
238
|
|
|
|
|
|
|
1 'baz' |
239
|
|
|
|
|
|
|
2 'foo' |
240
|
|
|
|
|
|
|
3 'import' |
241
|
|
|
|
|
|
|
4 'new' |
242
|
|
|
|
|
|
|
|
243
|
|
|
|
|
|
|
DB<3> x Class::Inspector->methods('Foo_Bar_Accessor'); |
244
|
|
|
|
|
|
|
0 ARRAY(0xfdb3c8) |
245
|
|
|
|
|
|
|
0 '_bar_accessor' |
246
|
|
|
|
|
|
|
1 '_baz_accessor' |
247
|
|
|
|
|
|
|
2 '_carp' |
248
|
|
|
|
|
|
|
3 '_croak' |
249
|
|
|
|
|
|
|
4 '_foo_accessor' |
250
|
|
|
|
|
|
|
5 '_mk_accessors' |
251
|
|
|
|
|
|
|
6 'accessor_name_for' |
252
|
|
|
|
|
|
|
7 'bar' |
253
|
|
|
|
|
|
|
8 'baz' |
254
|
|
|
|
|
|
|
9 'best_practice_accessor_name_for' |
255
|
|
|
|
|
|
|
10 'best_practice_mutator_name_for' |
256
|
|
|
|
|
|
|
11 'follow_best_practice' |
257
|
|
|
|
|
|
|
12 'foo' |
258
|
|
|
|
|
|
|
13 'get' |
259
|
|
|
|
|
|
|
14 'make_accessor' |
260
|
|
|
|
|
|
|
15 'make_ro_accessor' |
261
|
|
|
|
|
|
|
16 'make_wo_accessor' |
262
|
|
|
|
|
|
|
17 'mk_accessors' |
263
|
|
|
|
|
|
|
18 'mk_ro_accessors' |
264
|
|
|
|
|
|
|
19 'mk_wo_accessors' |
265
|
|
|
|
|
|
|
20 'mutator_name_for' |
266
|
|
|
|
|
|
|
21 'new' |
267
|
|
|
|
|
|
|
22 'set' |
268
|
|
|
|
|
|
|
|
269
|
|
|
|
|
|
|
As you can see, Object::Tiny adds 2 methods to your class, Class::Accessor |
270
|
|
|
|
|
|
|
adds 16 methods, plus one extra one for every accessor. |
271
|
|
|
|
|
|
|
|
272
|
|
|
|
|
|
|
B<Object::Tiny doesn't have any of the caveats of Class::Accessor::Fast> |
273
|
|
|
|
|
|
|
|
274
|
|
|
|
|
|
|
When you call B<use Object::Tiny qw{ foo bar baz }> it isn't treated as some |
275
|
|
|
|
|
|
|
sort of specification for the class, it's just a list of accessors you want |
276
|
|
|
|
|
|
|
made for you. |
277
|
|
|
|
|
|
|
|
278
|
|
|
|
|
|
|
So if you want to customize C<foo> you don't need to get into contortions with |
279
|
|
|
|
|
|
|
"pure" base classes or calling alternate internal methods. Just make your own |
280
|
|
|
|
|
|
|
C<foo> method and remove C<foo> from the list passed to the C<use> call. |
281
|
|
|
|
|
|
|
|
282
|
|
|
|
|
|
|
B<Object::Tiny is more back-compatible than Class::Accessor::Fast> |
283
|
|
|
|
|
|
|
|
284
|
|
|
|
|
|
|
Class::Accessor::Fast has a minimum Perl dependency of 5.005002. |
285
|
|
|
|
|
|
|
|
286
|
|
|
|
|
|
|
Object::Tiny has a minimum Perl dependency of 5.004. |
287
|
|
|
|
|
|
|
|
288
|
|
|
|
|
|
|
B<Object::Tiny has no module dependencies whatsoever> |
289
|
|
|
|
|
|
|
|
290
|
|
|
|
|
|
|
Object::Tiny does not load ANYTHING at all outside of its own single .pm file. |
291
|
|
|
|
|
|
|
|
292
|
|
|
|
|
|
|
So Object::Tiny will never get confused in odd situations due to old or weird |
293
|
|
|
|
|
|
|
versions of other modules (Class::Accessor::Fast has a dependency on base.pm, |
294
|
|
|
|
|
|
|
which has some caveats of its own). |
295
|
|
|
|
|
|
|
|
296
|
|
|
|
|
|
|
=head1 SUPPORT |
297
|
|
|
|
|
|
|
|
298
|
|
|
|
|
|
|
Bugs should be reported via the CPAN bug tracker at |
299
|
|
|
|
|
|
|
|
300
|
|
|
|
|
|
|
L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Object-Tiny> |
301
|
|
|
|
|
|
|
|
302
|
|
|
|
|
|
|
For other issues, contact the author. |
303
|
|
|
|
|
|
|
|
304
|
|
|
|
|
|
|
=head1 AUTHOR |
305
|
|
|
|
|
|
|
|
306
|
|
|
|
|
|
|
Adam Kennedy E<lt>adamk@cpan.orgE<gt> |
307
|
|
|
|
|
|
|
|
308
|
|
|
|
|
|
|
=head1 SEE ALSO |
309
|
|
|
|
|
|
|
|
310
|
|
|
|
|
|
|
L<Config::Tiny> |
311
|
|
|
|
|
|
|
|
312
|
|
|
|
|
|
|
=head1 COPYRIGHT |
313
|
|
|
|
|
|
|
|
314
|
|
|
|
|
|
|
Copyright 2007 - 2011 Adam Kennedy. |
315
|
|
|
|
|
|
|
|
316
|
|
|
|
|
|
|
This program is free software; you can redistribute |
317
|
|
|
|
|
|
|
it and/or modify it under the same terms as Perl itself. |
318
|
|
|
|
|
|
|
|
319
|
|
|
|
|
|
|
The full text of the license can be found in the |
320
|
|
|
|
|
|
|
LICENSE file included with this module. |
321
|
|
|
|
|
|
|
|
322
|
|
|
|
|
|
|
=cut |