| File | /usr/local/lib/perl5/site_perl/5.10.1/Exception/Class.pm |
| Statements Executed | 138 |
| Statement Execution Time | 1.96ms |
| Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
|---|---|---|---|---|---|
| 1 | 1 | 1 | 2.13ms | 16.5ms | Exception::Class::BEGIN@7 |
| 3 | 2 | 1 | 502µs | 708µs | Exception::Class::_make_subclass |
| 1 | 1 | 1 | 68µs | 807µs | Exception::Class::import |
| 1 | 1 | 1 | 26µs | 26µs | Exception::Class::BEGIN@3 |
| 1 | 1 | 1 | 18µs | 309µs | Exception::Class::_make_parents |
| 1 | 1 | 1 | 15µs | 30µs | Exception::Class::BEGIN@168 |
| 1 | 1 | 1 | 14µs | 57µs | Exception::Class::BEGIN@8 |
| 1 | 1 | 2 | 13µs | 13µs | Exception::Class::CORE:sort (opcode) |
| 1 | 1 | 1 | 11µs | 28µs | Exception::Class::BEGIN@45 |
| 1 | 1 | 1 | 11µs | 26µs | Exception::Class::BEGIN@78 |
| 1 | 1 | 1 | 7µs | 9µs | Exception::Class::BEGIN@5 |
| 1 | 1 | 1 | 6µs | 6µs | Exception::Class::BEGIN@11 |
| 3 | 1 | 2 | 4µs | 4µs | Exception::Class::CORE:subst (opcode) |
| 0 | 0 | 0 | 0s | 0s | Exception::Class::Classes |
| 0 | 0 | 0 | 0s | 0s | Exception::Class::__ANON__[:169] |
| 0 | 0 | 0 | 0s | 0s | Exception::Class::caught |
| Line | State ments |
Time on line |
Calls | Time in subs |
Code |
|---|---|---|---|---|---|
| 1 | package Exception::Class; | ||||
| 2 | |||||
| 3 | 3 | 37µs | 1 | 26µs | # spent 26µs within Exception::Class::BEGIN@3 which was called
# once (26µs+0s) by SimpleDB::Client::Exception::BEGIN@50 at line 3 # spent 26µs making 1 call to Exception::Class::BEGIN@3 |
| 4 | |||||
| 5 | 3 | 25µs | 2 | 12µs | # spent 9µs (7+2) within Exception::Class::BEGIN@5 which was called
# once (7µs+2µs) by SimpleDB::Client::Exception::BEGIN@50 at line 5 # spent 9µs making 1 call to Exception::Class::BEGIN@5
# spent 2µs making 1 call to strict::import |
| 6 | |||||
| 7 | 3 | 152µs | 1 | 16.5ms | # spent 16.5ms (2.13+14.3) within Exception::Class::BEGIN@7 which was called
# once (2.13ms+14.3ms) by SimpleDB::Client::Exception::BEGIN@50 at line 7 # spent 16.5ms making 1 call to Exception::Class::BEGIN@7 |
| 8 | 3 | 57µs | 2 | 99µs | # spent 57µs (14+43) within Exception::Class::BEGIN@8 which was called
# once (14µs+43µs) by SimpleDB::Client::Exception::BEGIN@50 at line 8 # spent 57µs making 1 call to Exception::Class::BEGIN@8
# spent 43µs making 1 call to Exporter::import |
| 9 | |||||
| 10 | 1 | 100ns | our $BASE_EXC_CLASS; | ||
| 11 | 1 | 187µs | 1 | 6µs | # spent 6µs within Exception::Class::BEGIN@11 which was called
# once (6µs+0s) by SimpleDB::Client::Exception::BEGIN@50 at line 11 # spent 6µs making 1 call to Exception::Class::BEGIN@11 |
| 12 | |||||
| 13 | 1 | 800ns | our $VERSION = '1.29'; | ||
| 14 | |||||
| 15 | 1 | 300ns | our %CLASSES; | ||
| 16 | |||||
| 17 | sub import | ||||
| 18 | # spent 807µs (68+739) within Exception::Class::import which was called
# once (68µs+739µs) by SimpleDB::Client::Exception::BEGIN@50 at line 52 of ../lib/SimpleDB/Client/Exception.pm | ||||
| 19 | 36 | 70µs | my $class = shift; | ||
| 20 | |||||
| 21 | local $Exception::Class::Caller = caller(); | ||||
| 22 | |||||
| 23 | my %c; | ||||
| 24 | |||||
| 25 | my %needs_parent; | ||||
| 26 | while (my $subclass = shift) | ||||
| 27 | { | ||||
| 28 | my $def = ref $_[0] ? shift : {}; | ||||
| 29 | $def->{isa} = $def->{isa} ? ( ref $def->{isa} ? $def->{isa} : [$def->{isa}] ) : []; | ||||
| 30 | |||||
| 31 | $c{$subclass} = $def; | ||||
| 32 | } | ||||
| 33 | |||||
| 34 | # We need to sort by length because if we check for keys in the | ||||
| 35 | # Foo::Bar:: stash, this creates a "Bar::" key in the Foo:: stash! | ||||
| 36 | MAKE_CLASSES: | ||||
| 37 | foreach my $subclass ( sort { length $a <=> length $b } keys %c ) # spent 13µs making 1 call to Exception::Class::CORE:sort | ||||
| 38 | { | ||||
| 39 | my $def = $c{$subclass}; | ||||
| 40 | |||||
| 41 | # We already made this one. | ||||
| 42 | next if $CLASSES{$subclass}; | ||||
| 43 | |||||
| 44 | { | ||||
| 45 | 3 | 212µs | 2 | 45µs | # spent 28µs (11+17) within Exception::Class::BEGIN@45 which was called
# once (11µs+17µs) by SimpleDB::Client::Exception::BEGIN@50 at line 45 # spent 28µs making 1 call to Exception::Class::BEGIN@45
# spent 17µs making 1 call to strict::unimport |
| 46 | foreach my $parent (@{ $def->{isa} }) | ||||
| 47 | { | ||||
| 48 | unless ( keys %{"$parent\::"} ) | ||||
| 49 | { | ||||
| 50 | $needs_parent{$subclass} = { parents => $def->{isa}, | ||||
| 51 | def => $def }; | ||||
| 52 | next MAKE_CLASSES; | ||||
| 53 | } | ||||
| 54 | } | ||||
| 55 | } | ||||
| 56 | |||||
| 57 | $class->_make_subclass( subclass => $subclass, # spent 417µs making 2 calls to Exception::Class::_make_subclass, avg 209µs/call | ||||
| 58 | def => $def || {}, | ||||
| 59 | ); | ||||
| 60 | } | ||||
| 61 | |||||
| 62 | foreach my $subclass (keys %needs_parent) | ||||
| 63 | { | ||||
| 64 | # This will be used to spot circular references. | ||||
| 65 | my %seen; | ||||
| 66 | $class->_make_parents( \%needs_parent, $subclass, \%seen ); # spent 309µs making 1 call to Exception::Class::_make_parents | ||||
| 67 | } | ||||
| 68 | } | ||||
| 69 | |||||
| 70 | sub _make_parents | ||||
| 71 | # spent 309µs (18+291) within Exception::Class::_make_parents which was called
# once (18µs+291µs) by Exception::Class::import at line 66 | ||||
| 72 | 10 | 14µs | my $class = shift; | ||
| 73 | my $needs = shift; | ||||
| 74 | my $subclass = shift; | ||||
| 75 | my $seen = shift; | ||||
| 76 | my $child = shift; # Just for error messages. | ||||
| 77 | |||||
| 78 | 3 | 466µs | 2 | 42µs | # spent 26µs (11+16) within Exception::Class::BEGIN@78 which was called
# once (11µs+16µs) by SimpleDB::Client::Exception::BEGIN@50 at line 78 # spent 26µs making 1 call to Exception::Class::BEGIN@78
# spent 16µs making 1 call to strict::unimport |
| 79 | |||||
| 80 | # What if someone makes a typo in specifying their 'isa' param? | ||||
| 81 | # This should catch it. Either it's been made because it didn't | ||||
| 82 | # have missing parents OR it's in our hash as needing a parent. | ||||
| 83 | # If neither of these is true then the _only_ place it is | ||||
| 84 | # mentioned is in the 'isa' param for some other class, which is | ||||
| 85 | # not a good enough reason to make a new class. | ||||
| 86 | die "Class $subclass appears to be a typo as it is only specified in the 'isa' param for $child\n" | ||||
| 87 | unless exists $needs->{$subclass} || $CLASSES{$subclass} || keys %{"$subclass\::"}; | ||||
| 88 | |||||
| 89 | foreach my $c ( @{ $needs->{$subclass}{parents} } ) | ||||
| 90 | { | ||||
| 91 | # It's been made | ||||
| 92 | next if $CLASSES{$c} || keys %{"$c\::"}; | ||||
| 93 | |||||
| 94 | die "There appears to be some circularity involving $subclass\n" | ||||
| 95 | if $seen->{$subclass}; | ||||
| 96 | |||||
| 97 | $seen->{$subclass} = 1; | ||||
| 98 | |||||
| 99 | $class->_make_parents( $needs, $c, $seen, $subclass ); | ||||
| 100 | } | ||||
| 101 | |||||
| 102 | return if $CLASSES{$subclass} || keys %{"$subclass\::"}; | ||||
| 103 | |||||
| 104 | $class->_make_subclass( subclass => $subclass, # spent 291µs making 1 call to Exception::Class::_make_subclass | ||||
| 105 | def => $needs->{$subclass}{def} ); | ||||
| 106 | } | ||||
| 107 | |||||
| 108 | sub _make_subclass | ||||
| 109 | { | ||||
| 110 | 65 | 231µs | my $class = shift; | ||
| 111 | my %p = @_; | ||||
| 112 | |||||
| 113 | my $subclass = $p{subclass}; | ||||
| 114 | my $def = $p{def}; | ||||
| 115 | |||||
| 116 | my $isa; | ||||
| 117 | if ($def->{isa}) | ||||
| 118 | { | ||||
| 119 | $isa = ref $def->{isa} ? join ' ', @{ $def->{isa} } : $def->{isa}; | ||||
| 120 | } | ||||
| 121 | $isa ||= $BASE_EXC_CLASS; | ||||
| 122 | |||||
| 123 | my $version_name = 'VERSION'; | ||||
| 124 | |||||
| 125 | my $code = <<"EOPERL"; | ||||
| 126 | package $subclass; | ||||
| 127 | |||||
| 128 | use base qw($isa); | ||||
| 129 | |||||
| 130 | our \$$version_name = '1.1'; | ||||
| 131 | |||||
| 132 | 1; | ||||
| 133 | |||||
| 134 | EOPERL | ||||
| 135 | |||||
| 136 | |||||
| 137 | if ($def->{description}) | ||||
| 138 | { | ||||
| 139 | (my $desc = $def->{description}) =~ s/([\\\'])/\\$1/g; # spent 4µs making 3 calls to Exception::Class::CORE:subst, avg 1µs/call | ||||
| 140 | $code .= <<"EOPERL"; | ||||
| 141 | sub description | ||||
| 142 | { | ||||
| 143 | return '$desc'; | ||||
| 144 | } | ||||
| 145 | EOPERL | ||||
| 146 | } | ||||
| 147 | |||||
| 148 | my @fields; | ||||
| 149 | if ( my $fields = $def->{fields} ) | ||||
| 150 | { | ||||
| 151 | @fields = UNIVERSAL::isa($fields, 'ARRAY') ? @$fields : $fields; # spent 2µs making 2 calls to UNIVERSAL::isa, avg 1µs/call | ||||
| 152 | |||||
| 153 | $code .= | ||||
| 154 | "sub Fields { return (\$_[0]->SUPER::Fields, " . | ||||
| 155 | join(", ", map { "'$_'" } @fields) . ") }\n\n"; | ||||
| 156 | |||||
| 157 | foreach my $field (@fields) | ||||
| 158 | { | ||||
| 159 | $code .= sprintf("sub %s { \$_[0]->{%s} }\n", $field, $field); | ||||
| 160 | } | ||||
| 161 | } | ||||
| 162 | |||||
| 163 | if ( my $alias = $def->{alias} ) | ||||
| 164 | { | ||||
| 165 | die "Cannot make alias without caller" | ||||
| 166 | unless defined $Exception::Class::Caller; | ||||
| 167 | |||||
| 168 | 3 | 202µs | 2 | 44µs | # spent 30µs (15+15) within Exception::Class::BEGIN@168 which was called
# once (15µs+15µs) by SimpleDB::Client::Exception::BEGIN@50 at line 168 # spent 30µs making 1 call to Exception::Class::BEGIN@168
# spent 14µs making 1 call to strict::unimport |
| 169 | *{"$Exception::Class::Caller\::$alias"} = sub { $subclass->throw(@_) }; | ||||
| 170 | } | ||||
| 171 | |||||
| 172 | 1 | 304µs | 6 | 364µs | eval $code; # spent 164µs making 3 calls to base::import, avg 55µs/call
# spent 67µs making 1 call to SimpleDB::Client::Exception::BEGIN@3
# spent 67µs making 1 call to SimpleDB::Client::Exception::Response::BEGIN@3
# spent 66µs making 1 call to SimpleDB::Client::Exception::Connection::BEGIN@3 |
| 173 | |||||
| 174 | die $@ if $@; | ||||
| 175 | |||||
| 176 | $CLASSES{$subclass} = 1; | ||||
| 177 | } | ||||
| 178 | |||||
| 179 | sub caught | ||||
| 180 | { | ||||
| 181 | my $e = $@; | ||||
| 182 | |||||
| 183 | return $e unless $_[1]; | ||||
| 184 | |||||
| 185 | return unless blessed($e) && $e->isa( $_[1] ); | ||||
| 186 | return $e; | ||||
| 187 | } | ||||
| 188 | |||||
| 189 | sub Classes { sort keys %Exception::Class::CLASSES } | ||||
| 190 | |||||
| 191 | 1 | 5µs | 1; | ||
| 192 | |||||
| 193 | __END__ | ||||
| 194 | |||||
| 195 | =head1 NAME | ||||
| 196 | |||||
| 197 | Exception::Class - A module that allows you to declare real exception classes in Perl | ||||
| 198 | |||||
| 199 | =head1 SYNOPSIS | ||||
| 200 | |||||
| 201 | use Exception::Class | ||||
| 202 | ( 'MyException', | ||||
| 203 | |||||
| 204 | 'AnotherException' => | ||||
| 205 | { isa => 'MyException' }, | ||||
| 206 | |||||
| 207 | 'YetAnotherException' => | ||||
| 208 | { isa => 'AnotherException', | ||||
| 209 | description => 'These exceptions are related to IPC' }, | ||||
| 210 | |||||
| 211 | 'ExceptionWithFields' => | ||||
| 212 | { isa => 'YetAnotherException', | ||||
| 213 | fields => [ 'grandiosity', 'quixotic' ], | ||||
| 214 | alias => 'throw_fields', | ||||
| 215 | }, | ||||
| 216 | ); | ||||
| 217 | |||||
| 218 | # try | ||||
| 219 | eval { MyException->throw( error => 'I feel funny.' ) }; | ||||
| 220 | |||||
| 221 | my $e; | ||||
| 222 | # catch | ||||
| 223 | if ( $e = Exception::Class->caught('MyException') ) | ||||
| 224 | { | ||||
| 225 | warn $e->error, "\n", $e->trace->as_string, "\n"; | ||||
| 226 | warn join ' ', $e->euid, $e->egid, $e->uid, $e->gid, $e->pid, $e->time; | ||||
| 227 | |||||
| 228 | exit; | ||||
| 229 | } | ||||
| 230 | elsif ( $e = Exception::Class->caught('ExceptionWithFields') ) | ||||
| 231 | { | ||||
| 232 | $e->quixotic ? do_something_wacky() : do_something_sane(); | ||||
| 233 | } | ||||
| 234 | else | ||||
| 235 | { | ||||
| 236 | $e = Exception::Class->caught(); | ||||
| 237 | ref $e ? $e->rethrow : die $e; | ||||
| 238 | } | ||||
| 239 | |||||
| 240 | # use an alias - without parens subroutine name is checked at | ||||
| 241 | # compile time | ||||
| 242 | throw_fields error => "No strawberry", grandiosity => "quite a bit"; | ||||
| 243 | |||||
| 244 | =head1 DESCRIPTION | ||||
| 245 | |||||
| 246 | Exception::Class allows you to declare exception hierarchies in your | ||||
| 247 | modules in a "Java-esque" manner. | ||||
| 248 | |||||
| 249 | It features a simple interface allowing programmers to 'declare' | ||||
| 250 | exception classes at compile time. It also has a base exception | ||||
| 251 | class, L<Exception::Class::Base>, that can be easily extended. | ||||
| 252 | |||||
| 253 | It is designed to make structured exception handling simpler and | ||||
| 254 | better by encouraging people to use hierarchies of exceptions in their | ||||
| 255 | applications, as opposed to a single catch-all exception class. | ||||
| 256 | |||||
| 257 | This module does not implement any try/catch syntax. Please see the | ||||
| 258 | "OTHER EXCEPTION MODULES (try/catch syntax)" section for more | ||||
| 259 | information on how to get this syntax. | ||||
| 260 | |||||
| 261 | You will also want to look at the documentation for | ||||
| 262 | L<Exception::Class::Base>, which is the default base class for all | ||||
| 263 | exception objects created by this module. | ||||
| 264 | |||||
| 265 | =head1 DECLARING EXCEPTION CLASSES | ||||
| 266 | |||||
| 267 | Importing C<Exception::Class> allows you to automagically create | ||||
| 268 | L<Exception::Class::Base> subclasses. You can also create subclasses | ||||
| 269 | via the traditional means of defining your own subclass with C<@ISA>. | ||||
| 270 | These two methods may be easily combined, so that you could subclass | ||||
| 271 | an exception class defined via the automagic import, if you desired | ||||
| 272 | this. | ||||
| 273 | |||||
| 274 | The syntax for the magic declarations is as follows: | ||||
| 275 | |||||
| 276 | 'MANDATORY CLASS NAME' => \%optional_hashref | ||||
| 277 | |||||
| 278 | The hashref may contain the following options: | ||||
| 279 | |||||
| 280 | =over 4 | ||||
| 281 | |||||
| 282 | =item * isa | ||||
| 283 | |||||
| 284 | This is the class's parent class. If this isn't provided then the | ||||
| 285 | class name in C<$Exception::Class::BASE_EXC_CLASS> is assumed to be | ||||
| 286 | the parent (see below). | ||||
| 287 | |||||
| 288 | This parameter lets you create arbitrarily deep class hierarchies. | ||||
| 289 | This can be any other L<Exception::Class::Base> subclass in your | ||||
| 290 | declaration I<or> a subclass loaded from a module. | ||||
| 291 | |||||
| 292 | To change the default exception class you will need to change the | ||||
| 293 | value of C<$Exception::Class::BASE_EXC_CLASS> I<before> calling | ||||
| 294 | C<import()>. To do this simply do something like this: | ||||
| 295 | |||||
| 296 | BEGIN { $Exception::Class::BASE_EXC_CLASS = 'SomeExceptionClass'; } | ||||
| 297 | |||||
| 298 | If anyone can come up with a more elegant way to do this please let me | ||||
| 299 | know. | ||||
| 300 | |||||
| 301 | CAVEAT: If you want to automagically subclass an | ||||
| 302 | L<Exception::Class::Base> subclass loaded from a file, then you | ||||
| 303 | I<must> compile the class (via use or require or some other magic) | ||||
| 304 | I<before> you import C<Exception::Class> or you'll get a compile time | ||||
| 305 | error. | ||||
| 306 | |||||
| 307 | =item * fields | ||||
| 308 | |||||
| 309 | This allows you to define additional attributes for your exception | ||||
| 310 | class. Any field you define can be passed to the C<throw()> or | ||||
| 311 | C<new()> methods as additional parameters for the constructor. In | ||||
| 312 | addition, your exception object will have an accessor method for the | ||||
| 313 | fields you define. | ||||
| 314 | |||||
| 315 | This parameter can be either a scalar (for a single field) or an array | ||||
| 316 | reference if you need to define multiple fields. | ||||
| 317 | |||||
| 318 | Fields will be inherited by subclasses. | ||||
| 319 | |||||
| 320 | =item * alias | ||||
| 321 | |||||
| 322 | Specifying an alias causes this class to create a subroutine of the | ||||
| 323 | specified name in the I<caller's> namespace. Calling this subroutine | ||||
| 324 | is equivalent to calling C<< <class>->throw(@_) >> for the given | ||||
| 325 | exception class. | ||||
| 326 | |||||
| 327 | Besides convenience, using aliases also allows for additional compile | ||||
| 328 | time checking. If the alias is called I<without parentheses>, as in | ||||
| 329 | C<throw_fields "an error occurred">, then Perl checks for the | ||||
| 330 | existence of the C<throw_fields()> subroutine at compile time. If | ||||
| 331 | instead you do C<< ExceptionWithFields->throw(...) >>, then Perl | ||||
| 332 | checks the class name at runtime, meaning that typos may sneak | ||||
| 333 | through. | ||||
| 334 | |||||
| 335 | =item * description | ||||
| 336 | |||||
| 337 | Each exception class has a description method that returns a fixed | ||||
| 338 | string. This should describe the exception I<class> (as opposed to | ||||
| 339 | any particular exception object). This may be useful for debugging if | ||||
| 340 | you start catching exceptions you weren't expecting (particularly if | ||||
| 341 | someone forgot to document them) and you don't understand the error | ||||
| 342 | messages. | ||||
| 343 | |||||
| 344 | =back | ||||
| 345 | |||||
| 346 | The C<Exception::Class> magic attempts to detect circular class | ||||
| 347 | hierarchies and will die if it finds one. It also detects missing | ||||
| 348 | links in a chain, for example if you declare Bar to be a subclass of | ||||
| 349 | Foo and never declare Foo. | ||||
| 350 | |||||
| 351 | =head1 Catching Exceptions | ||||
| 352 | |||||
| 353 | C<Exception::Class> provides some syntactic sugar for catching | ||||
| 354 | exceptions in a safe manner: | ||||
| 355 | |||||
| 356 | eval { ... } | ||||
| 357 | |||||
| 358 | if ( my $e = Exception::Class->caught('My::Error') ) | ||||
| 359 | { | ||||
| 360 | cleanup(); | ||||
| 361 | do_something_with_exception($e); | ||||
| 362 | } | ||||
| 363 | |||||
| 364 | The C<caught()> method takes a class name and returns an exception | ||||
| 365 | object if the last thrown exception is of the given class, or a | ||||
| 366 | subclass of that class. If it is not given any arguments, it simply | ||||
| 367 | returns C<$@>. | ||||
| 368 | |||||
| 369 | You should B<always> make a copy of the exception object, rather than | ||||
| 370 | using C<$@> directly. This is necessary because if your C<cleanup()> | ||||
| 371 | function uses C<eval>, or calls something which uses it, then C<$@> is | ||||
| 372 | overwritten. Copying the exception preserves it for the call to | ||||
| 373 | C<do_something_with_exception()>. | ||||
| 374 | |||||
| 375 | Exception objects also provide a caught method so you can write: | ||||
| 376 | |||||
| 377 | if ( my $e = My::Error->caught() ) | ||||
| 378 | { | ||||
| 379 | cleanup(); | ||||
| 380 | do_something_with_exception($e); | ||||
| 381 | } | ||||
| 382 | |||||
| 383 | =head2 Uncatchable Exceptions | ||||
| 384 | |||||
| 385 | Internally, the C<caught()> method will call C<isa()> on the exception | ||||
| 386 | object. You could make an exception "uncatchable" by overriding | ||||
| 387 | C<isa()> in that class like this: | ||||
| 388 | |||||
| 389 | package Exception::Uncatchable; | ||||
| 390 | |||||
| 391 | sub isa { shift->rethrow } | ||||
| 392 | |||||
| 393 | Of course, this only works if you always call | ||||
| 394 | C<< Exception::Class->caught() >> after an C<eval>. | ||||
| 395 | |||||
| 396 | =head1 USAGE RECOMMENDATION | ||||
| 397 | |||||
| 398 | If you're creating a complex system that throws lots of different | ||||
| 399 | types of exceptions, consider putting all the exception declarations | ||||
| 400 | in one place. For an app called Foo you might make a | ||||
| 401 | C<Foo::Exceptions> module and use that in all your code. This module | ||||
| 402 | could just contain the code to make C<Exception::Class> do its | ||||
| 403 | automagic class creation. Doing this allows you to more easily see | ||||
| 404 | what exceptions you have, and makes it easier to keep track of them. | ||||
| 405 | |||||
| 406 | This might look something like this: | ||||
| 407 | |||||
| 408 | package Foo::Bar::Exceptions; | ||||
| 409 | |||||
| 410 | use Exception::Class ( Foo::Bar::Exception::Senses => | ||||
| 411 | { description => 'sense-related exception' }, | ||||
| 412 | |||||
| 413 | Foo::Bar::Exception::Smell => | ||||
| 414 | { isa => 'Foo::Bar::Exception::Senses', | ||||
| 415 | fields => 'odor', | ||||
| 416 | description => 'stinky!' }, | ||||
| 417 | |||||
| 418 | Foo::Bar::Exception::Taste => | ||||
| 419 | { isa => 'Foo::Bar::Exception::Senses', | ||||
| 420 | fields => [ 'taste', 'bitterness' ], | ||||
| 421 | description => 'like, gag me with a spoon!' }, | ||||
| 422 | |||||
| 423 | ... ); | ||||
| 424 | |||||
| 425 | You may want to create a real module to subclass | ||||
| 426 | L<Exception::Class::Base> as well, particularly if you want your | ||||
| 427 | exceptions to have more methods. | ||||
| 428 | |||||
| 429 | =head2 Subclassing Exception::Class::Base | ||||
| 430 | |||||
| 431 | As part of your usage of C<Exception::Class>, you may want to create | ||||
| 432 | your own base exception class which subclasses | ||||
| 433 | L<Exception::Class::Base>. You should feel free to subclass any of | ||||
| 434 | the methods documented above. For example, you may want to subclass | ||||
| 435 | C<new()> to add additional information to your exception objects. | ||||
| 436 | |||||
| 437 | =head1 Exception::Class FUNCTIONS | ||||
| 438 | |||||
| 439 | The C<Exception::Class> method offers one function, C<Classes()>, | ||||
| 440 | which is not exported. This method returns a list of the classes that | ||||
| 441 | have been created by calling the C<Exception::Class> import() method. | ||||
| 442 | Note that this is I<all> the subclasses that have been created, so it | ||||
| 443 | may include subclasses created by things like CPAN modules, etc. Also | ||||
| 444 | note that if you simply define a subclass via the normal Perl method | ||||
| 445 | of setting C<@ISA> or C<use base>, then your subclass will not be | ||||
| 446 | included. | ||||
| 447 | |||||
| 448 | =head1 OTHER EXCEPTION MODULES (try/catch syntax) | ||||
| 449 | |||||
| 450 | If you are interested in adding try/catch/finally syntactic sugar to | ||||
| 451 | your code then I recommend you check out U. Arun Kumar's C<Error.pm> | ||||
| 452 | module, which implements this syntax. It also includes its own base | ||||
| 453 | exception class, C<Error::Simple>. | ||||
| 454 | |||||
| 455 | If you would prefer to use the L<Exception::Class::Base> class | ||||
| 456 | included with this module, you'll have to add this to your code | ||||
| 457 | somewhere: | ||||
| 458 | |||||
| 459 | push @Exception::Class::Base::ISA, 'Error' | ||||
| 460 | unless Exception::Class::Base->isa('Error'); | ||||
| 461 | |||||
| 462 | It's a hack but apparently it works. | ||||
| 463 | |||||
| 464 | =head1 SUPPORT | ||||
| 465 | |||||
| 466 | Please submit bugs to the CPAN RT system at | ||||
| 467 | http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Exception%3A%3AClass or | ||||
| 468 | via email at bug-exception-class@rt.cpan.org. | ||||
| 469 | |||||
| 470 | =head1 DONATIONS | ||||
| 471 | |||||
| 472 | If you'd like to thank me for the work I've done on this module, | ||||
| 473 | please consider making a "donation" to me via PayPal. I spend a lot of | ||||
| 474 | free time creating free software, and would appreciate any support | ||||
| 475 | you'd care to offer. | ||||
| 476 | |||||
| 477 | Please note that B<I am not suggesting that you must do this> in order | ||||
| 478 | for me to continue working on this particular software. I will | ||||
| 479 | continue to do so, inasmuch as I have in the past, for as long as it | ||||
| 480 | interests me. | ||||
| 481 | |||||
| 482 | Similarly, a donation made in this way will probably not make me work | ||||
| 483 | on this software much more, unless I get so many donations that I can | ||||
| 484 | consider working on free software full time, which seems unlikely at | ||||
| 485 | best. | ||||
| 486 | |||||
| 487 | To donate, log into PayPal and send money to autarch@urth.org or use | ||||
| 488 | the button on this page: | ||||
| 489 | L<http://www.urth.org/~autarch/fs-donation.html> | ||||
| 490 | |||||
| 491 | =head1 AUTHOR | ||||
| 492 | |||||
| 493 | Dave Rolsky, E<gt>autarch@urth.orgE<lt> | ||||
| 494 | |||||
| 495 | =head1 COPYRIGHT | ||||
| 496 | |||||
| 497 | Copyright (c) 2000-2009 David Rolsky. All rights reserved. This | ||||
| 498 | program is free software; you can redistribute it and/or modify it | ||||
| 499 | under the same terms as Perl itself. | ||||
| 500 | |||||
| 501 | The full text of the license can be found in the LICENSE file included | ||||
| 502 | with this module. | ||||
| 503 | |||||
| 504 | =cut | ||||
# spent 13µs within Exception::Class::CORE:sort which was called
# once (13µs+0s) by Exception::Class::import at line 37 of Exception/Class.pm | |||||
# spent 4µs within Exception::Class::CORE:subst which was called 3 times, avg 1µs/call:
# 3 times (4µs+0s) by Exception::Class::_make_subclass at line 139 of Exception/Class.pm, avg 1µs/call |