1Exception::Class(3) User Contributed Perl Documentation Exception::Class(3)
2
3
4
6 Exception::Class - A module that allows you to declare real exception
7 classes in Perl
8
10 version 1.37
11
13 use Exception::Class (
14 'MyException',
15
16 'AnotherException' => { isa => 'MyException' },
17
18 'YetAnotherException' => {
19 isa => 'AnotherException',
20 description => 'These exceptions are related to IPC'
21 },
22
23 'ExceptionWithFields' => {
24 isa => 'YetAnotherException',
25 fields => [ 'grandiosity', 'quixotic' ],
26 alias => 'throw_fields',
27 },
28 );
29 use Scalar::Util qw( blessed );
30 use Try::Tiny;
31
32 try {
33 MyException->throw( error => 'I feel funny.' );
34 }
35 catch {
36 die $_ unless blessed $_ && $_->can('rethrow');
37
38 if ( $_->isa('Exception::Class') ) {
39 warn $_->error, "\n", $_->trace->as_string, "\n";
40 warn join ' ', $_->euid, $_->egid, $_->uid, $_->gid, $_->pid, $_->time;
41
42 exit;
43 }
44 elsif ( $_->isa('ExceptionWithFields') ) {
45 if ( $_->quixotic ) {
46 handle_quixotic_exception();
47 }
48 else {
49 handle_non_quixotic_exception();
50 }
51 }
52 else {
53 $_->rethrow;
54 }
55 };
56
57 # without Try::Tiny
58
59 eval { ... };
60 if ( my $e = Exception::Class->caught() ) { ... }
61
62 # use an alias - without parens subroutine name is checked at
63 # compile time
64 throw_fields error => "No strawberry", grandiosity => "quite a bit";
65
67 RECOMMENDATION 1: If you are writing modern Perl code with Moose or Moo
68 I highly recommend using Throwable instead of this module.
69
70 RECOMMENDATION 2: Whether or not you use Throwable, you should use
71 Try::Tiny.
72
73 Exception::Class allows you to declare exception hierarchies in your
74 modules in a "Java-esque" manner.
75
76 It features a simple interface allowing programmers to 'declare'
77 exception classes at compile time. It also has a base exception class,
78 Exception::Class::Base, that can be easily extended.
79
80 It is designed to make structured exception handling simpler and better
81 by encouraging people to use hierarchies of exceptions in their
82 applications, as opposed to a single catch-all exception class.
83
84 This module does not implement any try/catch syntax. Please see the
85 "OTHER EXCEPTION MODULES (try/catch syntax)" section for more
86 information on how to get this syntax.
87
88 You will also want to look at the documentation for
89 Exception::Class::Base, which is the default base class for all
90 exception objects created by this module.
91
93 Importing "Exception::Class" allows you to automagically create
94 Exception::Class::Base subclasses. You can also create subclasses via
95 the traditional means of defining your own subclass with @ISA. These
96 two methods may be easily combined, so that you could subclass an
97 exception class defined via the automagic import, if you desired this.
98
99 The syntax for the magic declarations is as follows:
100
101 'MANDATORY CLASS NAME' => \%optional_hashref
102
103 The hashref may contain the following options:
104
105 · isa
106
107 This is the class's parent class. If this isn't provided then the
108 class name in $Exception::Class::BASE_EXC_CLASS is assumed to be
109 the parent (see below).
110
111 This parameter lets you create arbitrarily deep class hierarchies.
112 This can be any other Exception::Class::Base subclass in your
113 declaration or a subclass loaded from a module.
114
115 To change the default exception class you will need to change the
116 value of $Exception::Class::BASE_EXC_CLASS before calling
117 "import()". To do this simply do something like this:
118
119 BEGIN { $Exception::Class::BASE_EXC_CLASS = 'SomeExceptionClass'; }
120
121 If anyone can come up with a more elegant way to do this please let
122 me know.
123
124 CAVEAT: If you want to automagically subclass an
125 Exception::Class::Base subclass loaded from a file, then you must
126 compile the class (via use or require or some other magic) before
127 you import "Exception::Class" or you'll get a compile time error.
128
129 · fields
130
131 This allows you to define additional attributes for your exception
132 class. Any field you define can be passed to the "throw()" or
133 "new()" methods as additional parameters for the constructor. In
134 addition, your exception object will have an accessor method for
135 the fields you define.
136
137 This parameter can be either a scalar (for a single field) or an
138 array reference if you need to define multiple fields.
139
140 Fields will be inherited by subclasses.
141
142 · alias
143
144 Specifying an alias causes this class to create a subroutine of the
145 specified name in the caller's namespace. Calling this subroutine
146 is equivalent to calling "<class>->throw(@_)" for the given
147 exception class.
148
149 Besides convenience, using aliases also allows for additional
150 compile time checking. If the alias is called without parentheses,
151 as in "throw_fields "an error occurred"", then Perl checks for the
152 existence of the "throw_fields()" subroutine at compile time. If
153 instead you do "ExceptionWithFields->throw(...)", then Perl checks
154 the class name at runtime, meaning that typos may sneak through.
155
156 · description
157
158 Each exception class has a description method that returns a fixed
159 string. This should describe the exception class (as opposed to
160 any particular exception object). This may be useful for debugging
161 if you start catching exceptions you weren't expecting
162 (particularly if someone forgot to document them) and you don't
163 understand the error messages.
164
165 The "Exception::Class" magic attempts to detect circular class
166 hierarchies and will die if it finds one. It also detects missing
167 links in a chain, for example if you declare Bar to be a subclass of
168 Foo and never declare Foo.
169
171 If you are interested in adding try/catch/finally syntactic sugar to
172 your code then I recommend you check out Try::Tiny. This is a great
173 module that helps you ignore some of the weirdness with "eval" and $@.
174 Here's an example of how the two modules work together:
175
176 use Exception::Class ( 'My::Exception' );
177 use Scalar::Util qw( blessed );
178 use Try::Tiny;
179
180 try {
181 might_throw();
182 }
183 catch {
184 if ( blessed $_ && $_->isa('My::Exception') ) {
185 handle_it();
186 }
187 else {
188 die $_;
189 }
190 };
191
192 Note that you cannot use "Exception::Class->caught()" with Try::Tiny.
193
195 "Exception::Class" provides some syntactic sugar for catching
196 exceptions in a safe manner:
197
198 eval {...};
199
200 if ( my $e = Exception::Class->caught('My::Error') ) {
201 cleanup();
202 do_something_with_exception($e);
203 }
204
205 The "caught()" method takes a class name and returns an exception
206 object if the last thrown exception is of the given class, or a
207 subclass of that class. If it is not given any arguments, it simply
208 returns $@.
209
210 You should always make a copy of the exception object, rather than
211 using $@ directly. This is necessary because if your "cleanup()"
212 function uses "eval", or calls something which uses it, then $@ is
213 overwritten. Copying the exception preserves it for the call to
214 "do_something_with_exception()".
215
216 Exception objects also provide a caught method so you can write:
217
218 if ( my $e = My::Error->caught() ) {
219 cleanup();
220 do_something_with_exception($e);
221 }
222
223 Uncatchable Exceptions
224 Internally, the "caught()" method will call "isa()" on the exception
225 object. You could make an exception "uncatchable" by overriding
226 "isa()" in that class like this:
227
228 package Exception::Uncatchable;
229
230 sub isa { shift->rethrow }
231
232 Of course, this only works if you always call
233 "Exception::Class->caught()" after an "eval".
234
236 If you're creating a complex system that throws lots of different types
237 of exceptions, consider putting all the exception declarations in one
238 place. For an app called Foo you might make a "Foo::Exceptions" module
239 and use that in all your code. This module could just contain the code
240 to make "Exception::Class" do its automagic class creation. Doing this
241 allows you to more easily see what exceptions you have, and makes it
242 easier to keep track of them.
243
244 This might look something like this:
245
246 package Foo::Bar::Exceptions;
247
248 use Exception::Class (
249 Foo::Bar::Exception::Senses =>
250 { description => 'sense-related exception' },
251
252 Foo::Bar::Exception::Smell => {
253 isa => 'Foo::Bar::Exception::Senses',
254 fields => 'odor',
255 description => 'stinky!'
256 },
257
258 Foo::Bar::Exception::Taste => {
259 isa => 'Foo::Bar::Exception::Senses',
260 fields => [ 'taste', 'bitterness' ],
261 description => 'like, gag me with a spoon!'
262 },
263
264 ...
265 );
266
267 You may want to create a real module to subclass Exception::Class::Base
268 as well, particularly if you want your exceptions to have more methods.
269
270 Subclassing Exception::Class::Base
271 As part of your usage of "Exception::Class", you may want to create
272 your own base exception class which subclasses Exception::Class::Base.
273 You should feel free to subclass any of the methods documented above.
274 For example, you may want to subclass "new()" to add additional
275 information to your exception objects.
276
278 The "Exception::Class" method offers one function, "Classes()", which
279 is not exported. This method returns a list of the classes that have
280 been created by calling the "Exception::Class" import() method. Note
281 that this is all the subclasses that have been created, so it may
282 include subclasses created by things like CPAN modules, etc. Also note
283 that if you simply define a subclass via the normal Perl method of
284 setting @ISA or "use base", then your subclass will not be included.
285
287 Please submit bugs to the CPAN RT system at
288 http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Exception%3A%3AClass or
289 via email at bug-exception-class@rt.cpan.org.
290
292 If you'd like to thank me for the work I've done on this module, please
293 consider making a "donation" to me via PayPal. I spend a lot of free
294 time creating free software, and would appreciate any support you'd
295 care to offer.
296
297 Please note that I am not suggesting that you must do this in order for
298 me to continue working on this particular software. I will continue to
299 do so, inasmuch as I have in the past, for as long as it interests me.
300
301 Similarly, a donation made in this way will probably not make me work
302 on this software much more, unless I get so many donations that I can
303 consider working on free software full time, which seems unlikely at
304 best.
305
306 To donate, log into PayPal and send money to autarch@urth.org or use
307 the button on this page:
308 <http://www.urth.org/~autarch/fs-donation.html>
309
311 Dave Rolsky <autarch@urth.org>
312
314 This software is copyright (c) 2013 by Dave Rolsky.
315
316 This is free software; you can redistribute it and/or modify it under
317 the same terms as the Perl 5 programming language system itself.
318
319
320
321perl v5.16.3 2013-02-24 Exception::Class(3)