/Class-InsideOut-1.10/lib/Class/InsideOut.pod
Unknown | 467 lines | 311 code | 156 blank | 0 comment | 0 complexity | 9073cd015c8b09b1b66b6fde9027403a MD5 | raw file
Possible License(s): Apache-2.0
1# Generated by Pod::WikiDoc version 0.18
2
3=pod
4
5=head1 NAME
6
7Class::InsideOut - a safe, simple inside-out object construction kit
8
9=head1 VERSION
10
11This documentation refers to version 1.10
12
13=head1 SYNOPSIS
14
15 package My::Class;
16
17 use Class::InsideOut qw( public readonly private register id );
18
19 public name => my %name; # accessor: name()
20 readonly ssn => my %ssn; # read-only accessor: ssn()
21 private age => my %age; # no accessor
22
23 sub new { register( shift ) }
24
25 sub greeting {
26 my $self = shift;
27 return "Hello, my name is $name{ id $self }";
28 }
29
30=head1 DESCRIPTION
31
32This is a simple, safe and streamlined toolkit for building inside-out objects.
33Unlike most other inside-out object building modules already on CPAN, this
34module aims for minimalism and robustness:
35
36=over
37
38=item *
39
40Does not require derived classes to subclass it
41
42=item *
43
44Uses no source filters, attributes or C<<< CHECK >>> blocks
45
46=item *
47
48Supports any underlying object type including black-box inheritance
49
50=item *
51
52Does not leak memory on object destruction
53
54=item *
55
56Overloading-safe
57
58=item *
59
60Thread-safe for Perl 5.8.5 or better
61
62=item *
63
64C<<< mod_perl >>> compatible
65
66=item *
67
68Makes no assumption about inheritance or initializer needs
69
70=back
71
72It provides the minimal support necessary for creating safe inside-out objects
73and generating flexible accessors.
74
75=head2 Additional documentation
76
77=over
78
79=item *
80
81L<Class::InsideOut::Manual::About> -- Guide to the inside-out
82technique, the C<<< Class::InsideOut >>> philosophy, and other inside-out
83implementations
84
85=item *
86
87L<Class::InsideOut::Manual::Advanced> -- Advanced topics including customizing
88accessors, black-box inheritance, serialization and thread safety
89
90=back
91
92=head1 USAGE
93
94=head2 Importing C<<< Class::InsideOut >>>
95
96C<<< Class::InsideOut >>> automatically imports several critical methods into the
97calling package, including C<<< DESTROY >>> and support methods for serializing
98objects with C<<< Storable >>>. These methods are intimately tied to correct
99functioning of inside-out objects and will always be imported regardless
100of whether additional functions are requested.
101
102Additional functions may be imported as usual by including them as arguments to
103C<<< use >>>. For example:
104
105 use Class::InsideOut qw( register public );
106
107 public name => my %name;
108
109 sub new { register( shift ) }
110
111As a shortcut, C<<< Class::InsideOut >>> supports two tags for importing sets of
112functions:
113
114=over
115
116=item *
117
118C<<< :std >>> provides C<<< id >>>, C<<< private >>>, C<<< public >>>, C<<< readonly >>> and C<<< register >>>
119
120=item *
121
122C<<< :all >>> imports all functions (including an optional constructor)
123
124=back
125
126B<Note>: Automatic imports can be bypassed via C<<< require >>> or by passing an empty
127list to C<<< use Class::InsideOut >>>. There is almost no circumstance in which
128this is a good idea.
129
130=head2 Object properties and accessors
131
132Object properties are declared with the C<<< public >>>, C<<< readonly >>> and C<<< private >>>
133functions. They must be passed a label and the lexical hash that will be
134used to store object properties:
135
136 public name => my %name;
137 readonly ssn => my %ssn;
138 private age => my %age;
139
140Properties for an object are accessed through an index into the lexical hash
141based on the memory address of the object. This memory address I<must> be
142obtained via C<<< Scalar::Util::refaddr >>>. The alias C<<< id >>> may be imported for
143brevity.
144
145 $name{ refaddr $self } = "James";
146 $ssn { id $self } = 123456789;
147 $age { id $self } = 32;
148
149B<Tip>: since C<<< refaddr >>> and C<<< id >>> are function calls, it may be efficient to
150store the value once at the beginning of a method, particularly if it is being
151called repeatedly, e.g. within a loop.
152
153Object properties declared with C<<< public >>> will have an accessor created
154with the same name as the label. If the accessor is passed an argument, the
155property will be set to the argument. The accessor always returns the value of
156the property.
157
158 # Outside the class
159 $person = My::Class->new;
160 $person->name( "Larry" );
161
162Object properties declared with C<<< readonly >>> will have a read-only accessor
163created. The accessor will die if passed an argument to set the property
164value. The property may be set directly in the hash from within the class
165package as usual.
166
167 # Inside the class
168 $ssn { id $person } = 987654321;
169
170 # Inside or outside the class
171 $person->ssn( 123456789 ); # dies
172
173Property accessors may also be hand-written by declaring the property
174C<<< private >>> and writing whatever style of accessor is desired. For example:
175
176 sub age { $age{ id $_[0] } }
177 sub set_age { $age{ id $_[0] } = $_[1] }
178
179Hand-written accessors will be very slightly faster as generated accessors hold
180a reference to the property hash rather than accessing the property hash
181directly.
182
183It is also possible to use a package hash instead of a lexical hash to store
184object properties:
185
186 public name => our %name;
187
188However, this makes private object data accessable outside the class and incurs
189a slight performance penalty when accessing the property hash directly; it is
190not recommended to do this unless you really need it for some specialized
191reason.
192
193=head2 Object construction
194
195C<<< Class::InsideOut >>> provides no default constructor method as there are many
196possible ways of constructing an inside-out object. This avoids constraining
197users to any particular object initialization or superclass initialization
198methodology.
199
200By using the memory address of the object as the index for properties, I<any>
201type of reference may be used as the basis for an inside-out object with
202C<<< Class::InsideOut >>>.
203
204 sub new {
205 my $class = shift;
206
207 my $self = \( my $scalar ); # anonymous scalar
208 # my $self = {}; # anonymous hash
209 # my $self = []; # anonymous array
210 # open my $self, "<", $filename; # filehandle reference
211
212 bless $self, $class;
213 register( $self );
214 }
215
216However, to ensure that the inside-out object is thread-safe, the C<<< register >>>
217function I<must> be called on the newly created object. The C<<< register >>>
218function may also be called with just the class name for the common
219case of blessing an anonymous scalar.
220
221 register( $class ); # same as register( bless \(my $s), $class )
222
223As a convenience, C<<< Class::InsideOut >>> provides an optional C<<< new >>> constructor
224for simple objects. This constructor automatically initializes the object
225from keyE<sol>value pairs passed to the constructor for all keys matching the
226name of a property (including otherwise "private" or "readonly" properties).
227
228A more advanced technique for object construction uses another object, usually
229a superclass object, as the object reference. See "black-box inheritance" in
230L<Class::InsideOut::Manual::Advanced>.
231
232=head2 Object destruction
233
234C<<< Class::InsideOut >>> automatically exports a special C<<< DESTROY >>> function.
235This function cleans up object property memory for all declared properties the
236class and for all C<<< Class::InsideOut >>> based classes in the C<<< @ISA >>> array to
237avoid memory leaks or data collision.
238
239Additionally, if a user-supplied C<<< DEMOLISH >>> function is available in the same
240package, it will be called with the object being destroyed as its argument.
241C<<< DEMOLISH >>> can be used for custom destruction behavior such as updating class
242properties, closing sockets or closing database connections. Object properties
243will not be deleted until after C<<< DEMOLISH >>> returns.
244
245 # Sample DEMOLISH: Count objects demolished (for whatever reason)
246
247 my $objects_destroyed;
248
249 sub DEMOLISH {
250 $objects_destroyed++;
251 }
252
253C<<< DEMOLISH >>> will only be called if it exists for an object's actual
254class. C<<< DEMOLISH >>> will not be inherited and C<<< DEMOLISH >>> will not be called
255automatically for any superclasses.
256
257C<<< DEMOLISH >>> should manage any necessary calls to superclass C<<< DEMOLISH >>>
258methods. As with C<<< new >>>, implementation details are left to the user based on
259the user's approach to object inheritance. Depending on how the inheritance
260chain is constructed and how C<<< DEMOLISH >>> is being used, users may wish to
261entirely override superclass C<<< DEMOLISH >>> methods, rely upon C<<< SUPER::DEMOLISH >>>,
262or may prefer to walk the entire C<<< @ISA >>> tree:
263
264 use Class::ISA;
265
266 sub DEMOLISH {
267 my $self = shift;
268 # class specific demolish actions
269
270 # DEMOLISH for all parent classes, but only once
271 my @parents = Class::ISA::super_path( __PACKAGE__ );
272 my %called;
273 for my $p ( @parents ) {
274 my $demolish = $p->can('DEMOLISH');
275 $demolish->($self) if not $called{ $demolish }++;
276 }
277 }
278
279=head1 FUNCTIONS
280
281=head2 C<<< id >>>
282
283 $name{ id $object } = "Larry";
284
285This is a shorter, mnemonic alias for C<<< Scalar::Util::refaddr >>>. It returns the
286memory address of an object (just like C<<< refaddr >>>) as the index to access
287the properties of an inside-out object.
288
289=head2 C<<< new >>>
290
291 My::Class->new( name => "Larry", age => 42 );
292
293This simplistic constructor is provided as a convenience and is only exported
294on request. When called as a class method, it returns a blessed anonymous
295scalar. Arguments will be used to initialize all matching inside-out class
296properties in the C<<< @ISA >>> tree. The argument may be a hash or hash reference.
297
298Note: Properties are set directly, not via accessors. This means C<<< set_hook >>>
299functions will not be called. For more robust argument checking, you will
300need to implement your own constructor.
301
302=head2 C<<< options >>>
303
304 Class::InsideOut::options( \%new_options );
305 %current_options = Class::InsideOut::options();
306
307The C<<< options >>> function sets default options for use with all subsquent property
308definitions for the calling package. If called without arguments, this
309function will return the options currently in effect. When called with a hash
310reference of options, these will be joined with the existing defaults,
311overriding any options of the same name.
312
313=head2 C<<< private >>>
314
315 private weight => my %weight;
316 private haircolor => my %hair_color, { %options };
317
318This is an alias to C<<< property >>> that also sets the privacy option to 'private'.
319It will override default options or options passed as an argument.
320
321=head2 C<<< property >>>
322
323 property name => my %name;
324 property rank => my %rank, { %options };
325
326Declares an inside-out property. Two arguments are required and a third is
327optional. The first is a label for the property; this label will be used for
328introspection and generating accessors and thus must be a valid perl
329identifier. The second argument must be the lexical hash that will be used to
330store data for that property. Note that the C<<< my >>> keyword can be included as
331part of the argument rather than as a separate statement. The property will be
332tracked for memory cleanup during object destruction and for proper
333thread-safety.
334
335If a third, optional argument is provided, it must be a reference to a hash
336of options that will be applied to the property and will override any
337default options that have been set.
338
339=head2 C<<< public >>>
340
341 public height => my %height;
342 public age => my %age, { %options };
343
344This is an alias to C<<< property >>> that also sets the privacy option to 'public'.
345It will override default options or options passed as an argument.
346
347=head2 C<<< readonly >>>
348
349 readonly ssn => my %ssn;
350 readonly fingerprint => my %fingerprint, { %options };
351
352This is an alias to C<<< property >>> that sets the privacy option to 'public' and
353adds a C<<< set_hook >>> option that dies if an attempt is made to use the accessor to
354change the property. It will override default options or options passed as an
355argument.
356
357=head2 C<<< register >>>
358
359 register( bless( $object, $class ) ); # register the object
360 register( $reference, $class ); # automatic bless
361 register( $class ); # automatic blessed scalar
362
363Registers objects for thread-safety. This should be called as part of a
364constructor on a object blessed into the current package. Returns the
365resulting object. When called with only a class name, C<<< register >>> will bless an
366anonymous scalar reference into the given class. When called with both a
367reference and a class name, C<<< register >>> will bless the reference into the class.
368
369=head1 OPTIONS
370
371Options customize how properties are generated. Options may be set as a
372default with the C<<< options >>> function or passed as a hash reference to
373C<<< public >>>, C<<< private >>> or C<<< property >>>.
374
375Valid options include:
376
377=head2 C<<< privacy >>>
378
379 property rank => my %rank, { privacy => 'public' };
380 property serial => my %serial, { privacy => 'private' };
381
382If the I<privacy> option is set to I<public>, an accessor will be created
383with the same name as the label. If the accessor is passed an argument, the
384property will be set to the argument. The accessor always returns the value of
385the property.
386
387=head2 C<<< get_hook >>>
388
389 public list => my %list, {
390 get_hook => sub { @$_ }
391 };
392
393Defines an accessor hook for when values are retrieved. C<<< $_ >>> is locally
394aliased to the property value for the object. I<The return value of the hook is
395passed through as the return value of the accessor.> See "Customizing Accessors"
396in L<Class::InsideOut::Manual::Advanced> for details.
397
398=head2 C<<< set_hook >>>
399
400 public age => my %age, {
401 set_hook => sub { /^\d+$/ or die "must be an integer" }
402 };
403
404Defines an accessor hook for when values are set. The hook subroutine receives
405the entire argument list. C<<< $_ >>> is locally aliased to the first argument for
406convenience. The property receives the value of C<<< $_ >>>. See "Customizing
407Accessors" in L<Class::InsideOut::Manual::Advanced> for details.
408
409=head1 SEE ALSO
410
411Programmers seeking a more full-featured approach to inside-out objects are
412encouraged to explore L<Object::InsideOut>. Other implementations are also
413noted in L<Class::InsideOut::Manual::About>.
414
415=head1 KNOWN LIMITATIONS
416
417Requires weak reference support (Perl E<gt>= 5.6) and Scalar::Util::weaken() to
418avoid memory leaks and to provide thread-safety.
419
420=head1 ROADMAP
421
422Features slated for after the 1.0 release include:
423
424=over
425
426=item *
427
428Adding support for L<Data::Dump::Streamer> serialization hooks
429
430=item *
431
432Adding additional accessor styles (e.g. get_name()E<sol>set_name())
433
434=item *
435
436Further documentation revisions and clarification
437
438=back
439
440=head1 BUGS
441
442Please report bugs or feature requests using the CPAN Request Tracker:
443L<http://rt.cpan.org/Public/Dist/Display.html?Name=Class-InsideOut>
444
445When submitting a bug or request, please include a test-file or a patch to an
446existing test-file that illustrates the bug or desired feature.
447
448=head1 AUTHOR
449
450David A. Golden (DAGOLDEN)
451
452=head1 COPYRIGHT AND LICENSE
453
454Copyright (c) 2006, 2007 by David A. Golden
455
456Licensed under the Apache License, Version 2.0 (the "License");
457you may not use this file except in compliance with the License.
458You may obtain a copy of the License at
459LE<lt>http:E<sol>E<sol>www.apache.orgE<sol>licensesE<sol>LICENSE-2.0E<gt>
460
461Unless required by applicable law or agreed to in writing, software
462distributed under the License is distributed on an "AS IS" BASIS,
463WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
464See the License for the specific language governing permissions and
465limitations under the License.
466
467