1Class::Tiny(3)        User Contributed Perl Documentation       Class::Tiny(3)
2
3
4

NAME

6       Class::Tiny - Minimalist class construction
7

VERSION

9       version 1.006
10

SYNOPSIS

12       In Person.pm:
13
14         package Person;
15
16         use Class::Tiny qw( name );
17
18         1;
19
20       In Employee.pm:
21
22         package Employee;
23         use parent 'Person';
24
25         use Class::Tiny qw( ssn ), {
26           timestamp => sub { time }   # attribute with default
27         };
28
29         1;
30
31       In example.pl:
32
33         use Employee;
34
35         my $obj = Employee->new( name => "Larry", ssn => "111-22-3333" );
36
37         # unknown attributes are ignored
38         my $obj = Employee->new( name => "Larry", OS => "Linux" );
39         # $obj->{OS} does not exist
40

DESCRIPTION

42       This module offers a minimalist class construction kit in around 120
43       lines of code.  Here is a list of features:
44
45       ·   defines attributes via import arguments
46
47       ·   generates read-write accessors
48
49       ·   supports lazy attribute defaults
50
51       ·   supports custom accessors
52
53       ·   superclass provides a standard "new" constructor
54
55       ·   "new" takes a hash reference or list of key/value pairs
56
57       ·   "new" supports providing "BUILDARGS" to customize constructor
58           options
59
60       ·   "new" calls "BUILD" for each class from parent to child
61
62       ·   superclass provides a "DESTROY" method
63
64       ·   "DESTROY" calls "DEMOLISH" for each class from child to parent
65
66       Multiple-inheritance is possible, with superclass order determined via
67       mro::get_linear_isa.
68
69       It uses no non-core modules for any recent Perl. On Perls older than
70       v5.10 it requires MRO::Compat. On Perls older than v5.14, it requires
71       Devel::GlobalDestruction.
72

USAGE

74   Defining attributes
75       Define attributes as a list of import arguments:
76
77           package Foo::Bar;
78
79           use Class::Tiny qw(
80               name
81               id
82               height
83               weight
84           );
85
86       For each attribute, a read-write accessor is created unless a
87       subroutine of that name already exists:
88
89           $obj->name;               # getter
90           $obj->name( "John Doe" ); # setter
91
92       Attribute names must be valid subroutine identifiers or an exception
93       will be thrown.
94
95       You can specify lazy defaults by defining attributes with a hash
96       reference.  Keys define attribute names and values are constants or
97       code references that will be evaluated when the attribute is first
98       accessed if no value has been set.  The object is passed as an argument
99       to a code reference.
100
101           package Foo::WithDefaults;
102
103           use Class::Tiny qw/name id/, {
104               title     => 'Peon',
105               skills    => sub { [] },
106               hire_date => sub { $_[0]->_build_hire_date },
107           };
108
109       When subclassing, if multiple accessors of the same name exist in
110       different classes, any default (or lack of default) is determined by
111       standard method resolution order.
112
113       To make your own custom accessors, just pre-declare the method name
114       before loading Class::Tiny:
115
116           package Foo::Bar;
117
118           use subs 'id';
119
120           use Class::Tiny qw( name id );
121
122           sub id { ... }
123
124       Even if you pre-declare a method name, you must include it in the
125       attribute list for Class::Tiny to register it as a valid attribute.
126
127       If you set a default for a custom accessor, your accessor will need to
128       retrieve the default and do something with it:
129
130           package Foo::Bar;
131
132           use subs 'id';
133
134           use Class::Tiny qw( name ), { id => sub { int(rand(2*31)) } };
135
136           sub id {
137               my $self = shift;
138               if (@_) {
139                   return $self->{id} = shift;
140               }
141               elsif ( exists $self->{id} ) {
142                   return $self->{id};
143               }
144               else {
145                   my $defaults =
146                       Class::Tiny->get_all_attribute_defaults_for( ref $self );
147                   return $self->{id} = $defaults->{id}->();
148               }
149           }
150
151   Class::Tiny::Object is your base class
152       If your class does not already inherit from some class, then
153       Class::Tiny::Object will be added to your @ISA to provide "new" and
154       "DESTROY".
155
156       If your class does inherit from something, then no additional
157       inheritance is set up.  If the parent subclasses Class::Tiny::Object,
158       then all is well.  If not, then you'll get accessors set up but no
159       constructor or destructor. Don't do that unless you really have a
160       special need for it.
161
162       Define subclasses as normal.  It's best to define them with base,
163       parent or superclass before defining attributes with Class::Tiny so the
164       @ISA array is already populated at compile-time:
165
166           package Foo::Bar::More;
167
168           use parent 'Foo::Bar';
169
170           use Class::Tiny qw( shoe_size );
171
172   Object construction
173       If your class inherits from Class::Tiny::Object (as it should if you
174       followed the advice above), it provides the "new" constructor for you.
175
176       Objects can be created with attributes given as a hash reference or as
177       a list of key/value pairs:
178
179           $obj = Foo::Bar->new( name => "David" );
180
181           $obj = Foo::Bar->new( { name => "David" } );
182
183       If a reference is passed as a single argument, it must be able to be
184       dereferenced as a hash or an exception is thrown.
185
186       Unknown attributes in the constructor arguments will be ignored.  Prior
187       to version 1.000, unknown attributes were an error, but this made it
188       harder for people to cleanly subclass Class::Tiny classes so this
189       feature was removed.
190
191       You can define a "BUILDARGS" method to change how arguments to new are
192       handled.  It will receive the constructor arguments as they were
193       provided and must return a hash reference of key/value pairs (or else
194       throw an exception).
195
196           sub BUILDARGS {
197              my $class = shift;
198              my $name = shift || "John Doe";
199              return { name => $name };
200            };
201
202            Foo::Bar->new( "David" );
203            Foo::Bar->new(); # "John Doe"
204
205       Unknown attributes returned from "BUILDARGS" will be ignored.
206
207   BUILD
208       If your class or any superclass defines a "BUILD" method, it will be
209       called by the constructor from the furthest parent class down to the
210       child class after the object has been created.
211
212       It is passed the constructor arguments as a hash reference.  The return
213       value is ignored.  Use "BUILD" for validation, checking required
214       attributes or setting default values that depend on other attributes.
215
216           sub BUILD {
217               my ($self, $args) = @_;
218
219               for my $req ( qw/name age/ ) {
220                   croak "$req attribute required" unless defined $self->$req;
221               }
222
223               croak "Age must be non-negative" if $self->age < 0;
224
225               $self->msg( "Hello " . $self->name );
226           }
227
228       The argument reference is a copy, so deleting elements won't affect
229       data in the original (but changes will be passed to other BUILD methods
230       in @ISA).
231
232   DEMOLISH
233       Class::Tiny provides a "DESTROY" method.  If your class or any
234       superclass defines a "DEMOLISH" method, they will be called from the
235       child class to the furthest parent class during object destruction.  It
236       is provided a single boolean argument indicating whether Perl is in
237       global destruction.  Return values and errors are ignored.
238
239           sub DEMOLISH {
240               my ($self, $global_destruct) = @_;
241               $self->cleanup();
242           }
243
244   Introspection and internals
245       You can retrieve an unsorted list of valid attributes known to
246       Class::Tiny for a class and its superclasses with the
247       "get_all_attributes_for" class method.
248
249           my @attrs = Class::Tiny->get_all_attributes_for("Employee");
250           # returns qw/name ssn timestamp/
251
252       Likewise, a hash reference of all valid attributes and default values
253       (or code references) may be retrieved with the
254       "get_all_attribute_defaults_for" class method.  Any attributes without
255       a default will be "undef".
256
257           my $def = Class::Tiny->get_all_attribute_defaults_for("Employee");
258           # returns {
259           #   name => undef,
260           #   ssn => undef
261           #   timestamp => $coderef
262           # }
263
264       The "import" method uses two class methods, "prepare_class" and
265       "create_attributes" to set up the @ISA array and attributes.  Anyone
266       attempting to extend Class::Tiny itself should use these instead of
267       mocking up a call to "import".
268
269       When the first object is created, linearized @ISA, the valid attribute
270       list and various subroutine references are cached for speed.  Ensure
271       that all inheritance and methods are in place before creating objects.
272       (You don't want to be changing that once you create objects anyway,
273       right?)
274

RATIONALE

276   Why this instead of Object::Tiny or Class::Accessor or something else?
277       I wanted something so simple that it could potentially be used by core
278       Perl modules I help maintain (or hope to write), most of which either
279       use Class::Struct or roll-their-own OO framework each time.
280
281       Object::Tiny and Object::Tiny::RW were close to what I wanted, but
282       lacking some features I deemed necessary, and their maintainers have an
283       even more strict philosophy against feature creep than I have.
284
285       I also considered Class::Accessor, which has been around a long time
286       and is heavily used, but it, too, lacked features I wanted and did
287       things in ways I considered poor design.
288
289       I looked for something else on CPAN, but after checking a dozen class
290       creators I realized I could implement exactly what I wanted faster than
291       I could search CPAN for something merely sufficient.
292
293       In general, compared to most things on CPAN (other than Object::Tiny),
294       Class::Tiny is smaller in implementation and simpler in API.
295
296       Specifically, here is how Class::Tiny ("C::T") compares to Object::Tiny
297       ("O::T") and Class::Accessor ("C::A"):
298
299        FEATURE                            C::T    O::T      C::A
300        --------------------------------------------------------------
301        attributes defined via import      yes     yes       no
302        read/write accessors               yes     no        yes
303        lazy attribute defaults            yes     no        no
304        provides new                       yes     yes       yes
305        provides DESTROY                   yes     no        no
306        new takes either hashref or list   yes     no (list) no (hash)
307        Moo(se)-like BUILD/DEMOLISH        yes     no        no
308        Moo(se)-like BUILDARGS             yes     no        no
309        no extraneous methods via @ISA     yes     yes       no
310
311   Why this instead of Moose or Moo?
312       Moose and Moo are both excellent OO frameworks.  Moose offers a
313       powerful meta-object protocol (MOP), but is slow to start up and has
314       about 30 non-core dependencies including XS modules.  Moo is faster to
315       start up and has about 10 pure Perl dependencies but provides no true
316       MOP, relying instead on its ability to transparently upgrade Moo to
317       Moose when Moose's full feature set is required.
318
319       By contrast, Class::Tiny has no MOP and has zero non-core dependencies
320       for Perls in the support window.  It has far less code, less complexity
321       and no learning curve. If you don't need or can't afford what Moo or
322       Moose offer, this is intended to be a reasonable fallback.
323
324       That said, Class::Tiny offers Moose-like conventions for things like
325       "BUILD" and "DEMOLISH" for some minimal interoperability and an easier
326       upgrade path.
327

SUPPORT

329   Bugs / Feature Requests
330       Please report any bugs or feature requests through the issue tracker at
331       <https://github.com/dagolden/Class-Tiny/issues>.  You will be notified
332       automatically of any progress on your issue.
333
334   Source Code
335       This is open source software.  The code repository is available for
336       public review and contribution under the terms of the license.
337
338       <https://github.com/dagolden/Class-Tiny>
339
340         git clone https://github.com/dagolden/Class-Tiny.git
341

AUTHOR

343       David Golden <dagolden@cpan.org>
344

CONTRIBUTORS

346       ·   Dagfinn Ilmari Mannsåker <ilmari@ilmari.org>
347
348       ·   David Golden <xdg@xdg.me>
349
350       ·   Gelu Lupas <gelu@devnull.ro>
351
352       ·   Karen Etheridge <ether@cpan.org>
353
354       ·   Olivier Mengué <dolmen@cpan.org>
355
356       ·   Toby Inkster <tobyink@cpan.org>
357
359       This software is Copyright (c) 2013 by David Golden.
360
361       This is free software, licensed under:
362
363         The Apache License, Version 2.0, January 2004
364
365
366
367perl v5.30.1                      2020-01-29                    Class::Tiny(3)
Impressum