1Class::Tiny(3) User Contributed Perl Documentation Class::Tiny(3)
2
3
4
6 Class::Tiny - Minimalist class construction
7
9 version 1.006
10
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
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
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
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
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
343 David Golden <dagolden@cpan.org>
344
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.28.1 2016-09-10 Class::Tiny(3)