• Home
  • History
  • Annotate
Name Date Size #Lines LOC

..03-May-2022-

examples/H02-Apr-2017-95

lib/Class/H02-Apr-2017-1,525727

t/H02-Apr-2017-3,2572,449

xt/H02-Apr-2017-185125

CONTRIBUTING.mkdnH A D02-Apr-20173.4 KiB10165

ChangesH A D02-Apr-20178.1 KiB265157

LICENSEH A D02-Apr-201711.2 KiB208172

MANIFESTH A D02-Apr-20171.7 KiB7877

META.jsonH A D02-Apr-20173.2 KiB119117

META.ymlH A D02-Apr-20171.3 KiB5857

Makefile.PLH A D02-Apr-20171.7 KiB7867

READMEH A D02-Apr-201715.1 KiB409301

TodoH A D02-Apr-20172.5 KiB6750

cpanfileH A D02-Apr-20171.6 KiB5853

dist.iniH A D02-Apr-2017596 3026

perlcritic.rcH A D02-Apr-2017630 2720

README

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