| File | /project/perl/lib/Class/Accessor.pm |
| Statements Executed | 1958 |
| Statement Execution Time | 28.0ms |
| Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
|---|---|---|---|---|---|
| 463 | 3 | 2 | 18.3ms | 232ms | Class::Accessor::__ANON__[:395] |
| 6 | 1 | 1 | 4.59ms | 6.29ms | Class::Accessor::_mk_accessors |
| 15 | 2 | 2 | 1.48ms | 1.48ms | Class::Accessor::new |
| 30 | 1 | 1 | 527µs | 527µs | Class::Accessor::accessor_name_for |
| 30 | 1 | 1 | 499µs | 499µs | Class::Accessor::mutator_name_for |
| 17 | 2 | 2 | 410µs | 410µs | Class::Accessor::make_accessor |
| 6 | 6 | 6 | 315µs | 6.60ms | Class::Accessor::mk_accessors |
| 0 | 0 | 0 | 0s | 0s | Class::Accessor::BEGIN |
| 0 | 0 | 0 | 0s | 0s | Class::Accessor::__ANON__[:422] |
| 0 | 0 | 0 | 0s | 0s | Class::Accessor::__ANON__[:449] |
| 0 | 0 | 0 | 0s | 0s | Class::Accessor::_carp |
| 0 | 0 | 0 | 0s | 0s | Class::Accessor::_croak |
| 0 | 0 | 0 | 0s | 0s | Class::Accessor::best_practice_accessor_name_for |
| 0 | 0 | 0 | 0s | 0s | Class::Accessor::best_practice_mutator_name_for |
| 0 | 0 | 0 | 0s | 0s | Class::Accessor::follow_best_practice |
| 0 | 0 | 0 | 0s | 0s | Class::Accessor::get |
| 0 | 0 | 0 | 0s | 0s | Class::Accessor::make_ro_accessor |
| 0 | 0 | 0 | 0s | 0s | Class::Accessor::make_wo_accessor |
| 0 | 0 | 0 | 0s | 0s | Class::Accessor::mk_ro_accessors |
| 0 | 0 | 0 | 0s | 0s | Class::Accessor::mk_wo_accessors |
| 0 | 0 | 0 | 0s | 0s | Class::Accessor::set |
| Line | State ments |
Time on line |
Calls | Time in subs |
Code |
|---|---|---|---|---|---|
| 1 | package Class::Accessor; | ||||
| 2 | 1 | 5µs | require 5.00502; | ||
| 3 | 3 | 333µs | 1 | 24µs | use strict; # spent 24µs making 1 call to strict::import |
| 4 | 1 | 5µs | $Class::Accessor::VERSION = '0.30'; | ||
| 5 | |||||
| 6 | =head1 NAME | ||||
| 7 | |||||
| 8 | Class::Accessor - Automated accessor generation | ||||
| 9 | |||||
| 10 | =head1 SYNOPSIS | ||||
| 11 | |||||
| 12 | package Employee; | ||||
| 13 | use base qw(Class::Accessor); | ||||
| 14 | Employee->mk_accessors(qw(name role salary)); | ||||
| 15 | |||||
| 16 | # Meanwhile, in a nearby piece of code! | ||||
| 17 | # Class::Accessor provides new(). | ||||
| 18 | my $mp = Foo->new({ name => "Marty", role => "JAPH" }); | ||||
| 19 | |||||
| 20 | my $job = $mp->role; # gets $mp->{role} | ||||
| 21 | $mp->salary(400000); # sets $mp->{salary} = 400000 (I wish) | ||||
| 22 | |||||
| 23 | # like my @info = @{$mp}{qw(name role)} | ||||
| 24 | my @info = $mp->get(qw(name role)); | ||||
| 25 | |||||
| 26 | # $mp->{salary} = 400000 | ||||
| 27 | $mp->set('salary', 400000); | ||||
| 28 | |||||
| 29 | |||||
| 30 | =head1 DESCRIPTION | ||||
| 31 | |||||
| 32 | This module automagically generates accessors/mutators for your class. | ||||
| 33 | |||||
| 34 | Most of the time, writing accessors is an exercise in cutting and | ||||
| 35 | pasting. You usually wind up with a series of methods like this: | ||||
| 36 | |||||
| 37 | sub name { | ||||
| 38 | my $self = shift; | ||||
| 39 | if(@_) { | ||||
| 40 | $self->{name} = $_[0]; | ||||
| 41 | } | ||||
| 42 | return $self->{name}; | ||||
| 43 | } | ||||
| 44 | |||||
| 45 | sub salary { | ||||
| 46 | my $self = shift; | ||||
| 47 | if(@_) { | ||||
| 48 | $self->{salary} = $_[0]; | ||||
| 49 | } | ||||
| 50 | return $self->{salary}; | ||||
| 51 | } | ||||
| 52 | |||||
| 53 | # etc... | ||||
| 54 | |||||
| 55 | One for each piece of data in your object. While some will be unique, | ||||
| 56 | doing value checks and special storage tricks, most will simply be | ||||
| 57 | exercises in repetition. Not only is it Bad Style to have a bunch of | ||||
| 58 | repetitious code, but its also simply not lazy, which is the real | ||||
| 59 | tragedy. | ||||
| 60 | |||||
| 61 | If you make your module a subclass of Class::Accessor and declare your | ||||
| 62 | accessor fields with mk_accessors() then you'll find yourself with a | ||||
| 63 | set of automatically generated accessors which can even be | ||||
| 64 | customized! | ||||
| 65 | |||||
| 66 | The basic set up is very simple: | ||||
| 67 | |||||
| 68 | package My::Class; | ||||
| 69 | use base qw(Class::Accessor); | ||||
| 70 | My::Class->mk_accessors( qw(foo bar car) ); | ||||
| 71 | |||||
| 72 | Done. My::Class now has simple foo(), bar() and car() accessors | ||||
| 73 | defined. | ||||
| 74 | |||||
| 75 | =head2 What Makes This Different? | ||||
| 76 | |||||
| 77 | What makes this module special compared to all the other method | ||||
| 78 | generating modules (L<"SEE ALSO">)? By overriding the get() and set() | ||||
| 79 | methods you can alter the behavior of the accessors class-wide. Also, | ||||
| 80 | the accessors are implemented as closures which should cost a bit less | ||||
| 81 | memory than most other solutions which generate a new method for each | ||||
| 82 | accessor. | ||||
| 83 | |||||
| 84 | |||||
| 85 | =head1 METHODS | ||||
| 86 | |||||
| 87 | =head2 new | ||||
| 88 | |||||
| 89 | my $obj = Class->new; | ||||
| 90 | my $obj = $other_obj->new; | ||||
| 91 | |||||
| 92 | my $obj = Class->new(\%fields); | ||||
| 93 | my $obj = $other_obj->new(\%fields); | ||||
| 94 | |||||
| 95 | Class::Accessor provides a basic constructor. It generates a | ||||
| 96 | hash-based object and can be called as either a class method or an | ||||
| 97 | object method. | ||||
| 98 | |||||
| 99 | It takes an optional %fields hash which is used to initialize the | ||||
| 100 | object (handy if you use read-only accessors). The fields of the hash | ||||
| 101 | correspond to the names of your accessors, so... | ||||
| 102 | |||||
| 103 | package Foo; | ||||
| 104 | use base qw(Class::Accessor); | ||||
| 105 | Foo->mk_accessors('foo'); | ||||
| 106 | |||||
| 107 | my $obj = Class->new({ foo => 42 }); | ||||
| 108 | print $obj->foo; # 42 | ||||
| 109 | |||||
| 110 | however %fields can contain anything, new() will shove them all into | ||||
| 111 | your object. Don't like it? Override it. | ||||
| 112 | |||||
| 113 | =cut | ||||
| 114 | |||||
| 115 | # spent 1.48ms within Class::Accessor::new which was called 15 times, avg 99µs/call:
# 10 times (1.16ms+0s) by Class::DBI::Column::new at line 52 of Class/DBI/Column.pm, avg 116µs/call
# 5 times (320µs+0s) by Class::DBI::Relationship::_init at line 24 of Class/DBI/Relationship.pm, avg 64µs/call | ||||
| 116 | 15 | 87µs | my($proto, $fields) = @_; | ||
| 117 | 15 | 90µs | my($class) = ref $proto || $proto; | ||
| 118 | |||||
| 119 | 15 | 66µs | $fields = {} unless defined $fields; | ||
| 120 | |||||
| 121 | # make a copy of $fields. | ||||
| 122 | 15 | 1.28ms | bless {%$fields}, $class; | ||
| 123 | } | ||||
| 124 | |||||
| 125 | =head2 mk_accessors | ||||
| 126 | |||||
| 127 | Class->mk_accessors(@fields); | ||||
| 128 | |||||
| 129 | This creates accessor/mutator methods for each named field given in | ||||
| 130 | @fields. Foreach field in @fields it will generate two accessors. | ||||
| 131 | One called "field()" and the other called "_field_accessor()". For | ||||
| 132 | example: | ||||
| 133 | |||||
| 134 | # Generates foo(), _foo_accessor(), bar() and _bar_accessor(). | ||||
| 135 | Class->mk_accessors(qw(foo bar)); | ||||
| 136 | |||||
| 137 | See L<CAVEATS AND TRICKS/"Overriding autogenerated accessors"> | ||||
| 138 | for details. | ||||
| 139 | |||||
| 140 | =cut | ||||
| 141 | |||||
| 142 | # spent 6.60ms (315µs+6.29) within Class::Accessor::mk_accessors which was called 6 times, avg 1.10ms/call:
# once (53µs+1.43ms) by base::import at line 35 of Class/DBI/Query.pm
# once (55µs+1.29ms) by base::import at line 16 of Class/DBI/Plugin/Pager.pm
# once (57µs+1.06ms) by base::import at line 32 of Class/DBI/Column.pm
# once (48µs+1.01ms) by base::import at line 8 of Class/DBI/Relationship.pm
# once (51µs+854µs) by Class::DBI::_require_class at line 83 of Class/DBI/Search/Basic.pm
# once (51µs+640µs) by base::import at line 5 of Data/Page.pm | ||||
| 143 | 6 | 67µs | my($self, @fields) = @_; | ||
| 144 | |||||
| 145 | 6 | 230µs | 6 | 6.29ms | $self->_mk_accessors('rw', @fields); # spent 6.29ms making 6 calls to Class::Accessor::_mk_accessors, avg 1.05ms/call |
| 146 | } | ||||
| 147 | |||||
| 148 | |||||
| 149 | { | ||||
| 150 | 4 | 1.90ms | 1 | 115µs | no strict 'refs'; # spent 115µs making 1 call to strict::unimport |
| 151 | |||||
| 152 | # spent 6.29ms (4.59+1.70) within Class::Accessor::_mk_accessors which was called 6 times, avg 1.05ms/call:
# 6 times (4.59ms+1.70ms) by Class::Accessor::mk_accessors at line 145, avg 1.05ms/call | ||||
| 153 | 6 | 52µs | my($self, $access, @fields) = @_; | ||
| 154 | 6 | 35µs | my $class = ref $self || $self; | ||
| 155 | 6 | 64µs | my $ra = $access eq 'rw' || $access eq 'ro'; | ||
| 156 | 6 | 29µs | my $wa = $access eq 'rw' || $access eq 'wo'; | ||
| 157 | |||||
| 158 | 6 | 135µs | foreach my $field (@fields) { | ||
| 159 | 30 | 724µs | 30 | 527µs | my $accessor_name = $self->accessor_name_for($field); # spent 527µs making 30 calls to Class::Accessor::accessor_name_for, avg 18µs/call |
| 160 | 30 | 657µs | 30 | 499µs | my $mutator_name = $self->mutator_name_for($field); # spent 499µs making 30 calls to Class::Accessor::mutator_name_for, avg 17µs/call |
| 161 | 30 | 142µs | if( $accessor_name eq 'DESTROY' or $mutator_name eq 'DESTROY' ) { | ||
| 162 | $self->_carp("Having a data accessor named DESTROY in '$class' is unwise."); | ||||
| 163 | } | ||||
| 164 | 30 | 443µs | if ($accessor_name eq $mutator_name) { | ||
| 165 | 30 | 157µs | my $accessor; | ||
| 166 | 30 | 620µs | 30 | 672µs | if ($ra && $wa) { # spent 315µs making 14 calls to Class::Accessor::Fast::make_accessor, avg 23µs/call
# spent 202µs making 9 calls to Class::Accessor::Chained::Fast::make_accessor, avg 22µs/call
# spent 155µs making 7 calls to Class::Accessor::make_accessor, avg 22µs/call |
| 167 | $accessor = $self->make_accessor($field); | ||||
| 168 | } elsif ($ra) { | ||||
| 169 | $accessor = $self->make_ro_accessor($field); | ||||
| 170 | } else { | ||||
| 171 | $accessor = $self->make_wo_accessor($field); | ||||
| 172 | } | ||||
| 173 | 30 | 414µs | unless (defined &{"${class}::$accessor_name"}) { | ||
| 174 | *{"${class}::$accessor_name"} = $accessor; | ||||
| 175 | } | ||||
| 176 | 30 | 323µs | if ($accessor_name eq $field) { | ||
| 177 | # the old behaviour | ||||
| 178 | 30 | 172µs | my $alias = "_${field}_accessor"; | ||
| 179 | 30 | 335µs | *{"${class}::$alias"} = $accessor unless defined &{"${class}::$alias"}; | ||
| 180 | } | ||||
| 181 | } else { | ||||
| 182 | if ($ra and not defined &{"${class}::$accessor_name"}) { | ||||
| 183 | *{"${class}::$accessor_name"} = $self->make_ro_accessor($field); | ||||
| 184 | } | ||||
| 185 | if ($wa and not defined &{"${class}::$mutator_name"}) { | ||||
| 186 | *{"${class}::$mutator_name"} = $self->make_wo_accessor($field); | ||||
| 187 | } | ||||
| 188 | } | ||||
| 189 | } | ||||
| 190 | } | ||||
| 191 | |||||
| 192 | sub follow_best_practice { | ||||
| 193 | my($self) = @_; | ||||
| 194 | my $class = ref $self || $self; | ||||
| 195 | *{"${class}::accessor_name_for"} = \&best_practice_accessor_name_for; | ||||
| 196 | *{"${class}::mutator_name_for"} = \&best_practice_mutator_name_for; | ||||
| 197 | } | ||||
| 198 | |||||
| 199 | } | ||||
| 200 | |||||
| 201 | =head2 mk_ro_accessors | ||||
| 202 | |||||
| 203 | Class->mk_ro_accessors(@read_only_fields); | ||||
| 204 | |||||
| 205 | Same as mk_accessors() except it will generate read-only accessors | ||||
| 206 | (ie. true accessors). If you attempt to set a value with these | ||||
| 207 | accessors it will throw an exception. It only uses get() and not | ||||
| 208 | set(). | ||||
| 209 | |||||
| 210 | package Foo; | ||||
| 211 | use base qw(Class::Accessor); | ||||
| 212 | Class->mk_ro_accessors(qw(foo bar)); | ||||
| 213 | |||||
| 214 | # Let's assume we have an object $foo of class Foo... | ||||
| 215 | print $foo->foo; # ok, prints whatever the value of $foo->{foo} is | ||||
| 216 | $foo->foo(42); # BOOM! Naughty you. | ||||
| 217 | |||||
| 218 | |||||
| 219 | =cut | ||||
| 220 | |||||
| 221 | sub mk_ro_accessors { | ||||
| 222 | my($self, @fields) = @_; | ||||
| 223 | |||||
| 224 | $self->_mk_accessors('ro', @fields); | ||||
| 225 | } | ||||
| 226 | |||||
| 227 | =head2 mk_wo_accessors | ||||
| 228 | |||||
| 229 | Class->mk_wo_accessors(@write_only_fields); | ||||
| 230 | |||||
| 231 | Same as mk_accessors() except it will generate write-only accessors | ||||
| 232 | (ie. mutators). If you attempt to read a value with these accessors | ||||
| 233 | it will throw an exception. It only uses set() and not get(). | ||||
| 234 | |||||
| 235 | B<NOTE> I'm not entirely sure why this is useful, but I'm sure someone | ||||
| 236 | will need it. If you've found a use, let me know. Right now its here | ||||
| 237 | for orthoginality and because its easy to implement. | ||||
| 238 | |||||
| 239 | package Foo; | ||||
| 240 | use base qw(Class::Accessor); | ||||
| 241 | Class->mk_wo_accessors(qw(foo bar)); | ||||
| 242 | |||||
| 243 | # Let's assume we have an object $foo of class Foo... | ||||
| 244 | $foo->foo(42); # OK. Sets $self->{foo} = 42 | ||||
| 245 | print $foo->foo; # BOOM! Can't read from this accessor. | ||||
| 246 | |||||
| 247 | =cut | ||||
| 248 | |||||
| 249 | sub mk_wo_accessors { | ||||
| 250 | my($self, @fields) = @_; | ||||
| 251 | |||||
| 252 | $self->_mk_accessors('wo', @fields); | ||||
| 253 | } | ||||
| 254 | |||||
| 255 | =head1 DETAILS | ||||
| 256 | |||||
| 257 | An accessor generated by Class::Accessor looks something like | ||||
| 258 | this: | ||||
| 259 | |||||
| 260 | # Your foo may vary. | ||||
| 261 | sub foo { | ||||
| 262 | my($self) = shift; | ||||
| 263 | if(@_) { # set | ||||
| 264 | return $self->set('foo', @_); | ||||
| 265 | } | ||||
| 266 | else { | ||||
| 267 | return $self->get('foo'); | ||||
| 268 | } | ||||
| 269 | } | ||||
| 270 | |||||
| 271 | Very simple. All it does is determine if you're wanting to set a | ||||
| 272 | value or get a value and calls the appropriate method. | ||||
| 273 | Class::Accessor provides default get() and set() methods which | ||||
| 274 | your class can override. They're detailed later. | ||||
| 275 | |||||
| 276 | =head2 follow_best_practice | ||||
| 277 | |||||
| 278 | In Damian's Perl Best Practices book he recommends separate get and set methods | ||||
| 279 | with the prefix set_ and get_ to make it explicit what you intend to do. If you | ||||
| 280 | want to create those accessor methods instead of the default ones, call: | ||||
| 281 | |||||
| 282 | __PACKAGE__->follow_best_practice | ||||
| 283 | |||||
| 284 | =head2 accessor_name_for / mutator_name_for | ||||
| 285 | |||||
| 286 | You may have your own crazy ideas for the names of the accessors, so you can | ||||
| 287 | make those happen by overriding C<accessor_name_for> and C<mutator_name_for> in | ||||
| 288 | your subclass. (I copied that idea from Class::DBI.) | ||||
| 289 | |||||
| 290 | =cut | ||||
| 291 | |||||
| 292 | sub best_practice_accessor_name_for { | ||||
| 293 | my ($class, $field) = @_; | ||||
| 294 | return "get_$field"; | ||||
| 295 | } | ||||
| 296 | |||||
| 297 | sub best_practice_mutator_name_for { | ||||
| 298 | my ($class, $field) = @_; | ||||
| 299 | return "set_$field"; | ||||
| 300 | } | ||||
| 301 | |||||
| 302 | # spent 527µs within Class::Accessor::accessor_name_for which was called 30 times, avg 18µs/call:
# 30 times (527µs+0s) by Class::Accessor::_mk_accessors at line 159, avg 18µs/call | ||||
| 303 | 30 | 162µs | my ($class, $field) = @_; | ||
| 304 | 30 | 484µs | return $field; | ||
| 305 | } | ||||
| 306 | |||||
| 307 | # spent 499µs within Class::Accessor::mutator_name_for which was called 30 times, avg 17µs/call:
# 30 times (499µs+0s) by Class::Accessor::_mk_accessors at line 160, avg 17µs/call | ||||
| 308 | 30 | 158µs | my ($class, $field) = @_; | ||
| 309 | 30 | 397µs | return $field; | ||
| 310 | } | ||||
| 311 | |||||
| 312 | =head2 Modifying the behavior of the accessor | ||||
| 313 | |||||
| 314 | Rather than actually modifying the accessor itself, it is much more | ||||
| 315 | sensible to simply override the two key methods which the accessor | ||||
| 316 | calls. Namely set() and get(). | ||||
| 317 | |||||
| 318 | If you -really- want to, you can override make_accessor(). | ||||
| 319 | |||||
| 320 | =head2 set | ||||
| 321 | |||||
| 322 | $obj->set($key, $value); | ||||
| 323 | $obj->set($key, @values); | ||||
| 324 | |||||
| 325 | set() defines how generally one stores data in the object. | ||||
| 326 | |||||
| 327 | override this method to change how data is stored by your accessors. | ||||
| 328 | |||||
| 329 | =cut | ||||
| 330 | |||||
| 331 | sub set { | ||||
| 332 | my($self, $key) = splice(@_, 0, 2); | ||||
| 333 | |||||
| 334 | if(@_ == 1) { | ||||
| 335 | $self->{$key} = $_[0]; | ||||
| 336 | } | ||||
| 337 | elsif(@_ > 1) { | ||||
| 338 | $self->{$key} = [@_]; | ||||
| 339 | } | ||||
| 340 | else { | ||||
| 341 | $self->_croak("Wrong number of arguments received"); | ||||
| 342 | } | ||||
| 343 | } | ||||
| 344 | |||||
| 345 | =head2 get | ||||
| 346 | |||||
| 347 | $value = $obj->get($key); | ||||
| 348 | @values = $obj->get(@keys); | ||||
| 349 | |||||
| 350 | get() defines how data is retreived from your objects. | ||||
| 351 | |||||
| 352 | override this method to change how it is retreived. | ||||
| 353 | |||||
| 354 | =cut | ||||
| 355 | |||||
| 356 | sub get { | ||||
| 357 | my $self = shift; | ||||
| 358 | |||||
| 359 | if(@_ == 1) { | ||||
| 360 | return $self->{$_[0]}; | ||||
| 361 | } | ||||
| 362 | elsif( @_ > 1 ) { | ||||
| 363 | return @{$self}{@_}; | ||||
| 364 | } | ||||
| 365 | else { | ||||
| 366 | $self->_croak("Wrong number of arguments received"); | ||||
| 367 | } | ||||
| 368 | } | ||||
| 369 | |||||
| 370 | =head2 make_accessor | ||||
| 371 | |||||
| 372 | $accessor = Class->make_accessor($field); | ||||
| 373 | |||||
| 374 | Generates a subroutine reference which acts as an accessor for the given | ||||
| 375 | $field. It calls get() and set(). | ||||
| 376 | |||||
| 377 | If you wish to change the behavior of your accessors, try overriding | ||||
| 378 | get() and set() before you start mucking with make_accessor(). | ||||
| 379 | |||||
| 380 | =cut | ||||
| 381 | |||||
| 382 | # spent 410µs within Class::Accessor::make_accessor which was called 17 times, avg 24µs/call:
# 10 times (255µs+0s) by Class::DBI::_mk_column_accessors at line 359 of Class/DBI.pm, avg 26µs/call
# 7 times (155µs+0s) by Class::Accessor::_mk_accessors at line 166, avg 22µs/call | ||||
| 383 | 17 | 101µs | my ($class, $field) = @_; | ||
| 384 | |||||
| 385 | # Build a closure around $field. | ||||
| 386 | # spent 232ms (18.3+214) within Class::Accessor::__ANON__[/project/perl/lib/Class/Accessor.pm:395] which was called 463 times, avg 501µs/call:
# 461 times (18.2ms+202ms) by main::RUNTIME at line 8 of ddd2.pl, avg 477µs/call
# once (40µs+11.3ms) by main::RUNTIME at line 10 of ddd2.pl
# once (39µs+419µs) by Class::DBI::_flesh at line 857 of Class/DBI.pm | ||||
| 387 | 463 | 2.77ms | my $self = shift; | ||
| 388 | |||||
| 389 | 463 | 2.16ms | if(@_) { | ||
| 390 | return $self->set($field, @_); | ||||
| 391 | } | ||||
| 392 | else { | ||||
| 393 | 463 | 12.7ms | 463 | 213ms | return $self->get($field); # spent 214ms making 463 calls to Class::DBI::get, avg 461µs/call, recursion: max depth 1, time 419µs |
| 394 | } | ||||
| 395 | 17 | 400µs | }; | ||
| 396 | } | ||||
| 397 | |||||
| 398 | =head2 make_ro_accessor | ||||
| 399 | |||||
| 400 | $read_only_accessor = Class->make_ro_accessor($field); | ||||
| 401 | |||||
| 402 | Generates a subroutine refrence which acts as a read-only accessor for | ||||
| 403 | the given $field. It only calls get(). | ||||
| 404 | |||||
| 405 | Override get() to change the behavior of your accessors. | ||||
| 406 | |||||
| 407 | =cut | ||||
| 408 | |||||
| 409 | sub make_ro_accessor { | ||||
| 410 | my($class, $field) = @_; | ||||
| 411 | |||||
| 412 | return sub { | ||||
| 413 | my $self = shift; | ||||
| 414 | |||||
| 415 | if (@_) { | ||||
| 416 | my $caller = caller; | ||||
| 417 | $self->_croak("'$caller' cannot alter the value of '$field' on objects of class '$class'"); | ||||
| 418 | } | ||||
| 419 | else { | ||||
| 420 | return $self->get($field); | ||||
| 421 | } | ||||
| 422 | }; | ||||
| 423 | } | ||||
| 424 | |||||
| 425 | =head2 make_wo_accessor | ||||
| 426 | |||||
| 427 | $read_only_accessor = Class->make_wo_accessor($field); | ||||
| 428 | |||||
| 429 | Generates a subroutine refrence which acts as a write-only accessor | ||||
| 430 | (mutator) for the given $field. It only calls set(). | ||||
| 431 | |||||
| 432 | Override set() to change the behavior of your accessors. | ||||
| 433 | |||||
| 434 | =cut | ||||
| 435 | |||||
| 436 | sub make_wo_accessor { | ||||
| 437 | my($class, $field) = @_; | ||||
| 438 | |||||
| 439 | return sub { | ||||
| 440 | my $self = shift; | ||||
| 441 | |||||
| 442 | unless (@_) { | ||||
| 443 | my $caller = caller; | ||||
| 444 | $self->_croak("'$caller' cannot access the value of '$field' on objects of class '$class'"); | ||||
| 445 | } | ||||
| 446 | else { | ||||
| 447 | return $self->set($field, @_); | ||||
| 448 | } | ||||
| 449 | }; | ||||
| 450 | } | ||||
| 451 | |||||
| 452 | =head1 EXCEPTIONS | ||||
| 453 | |||||
| 454 | If something goes wrong Class::Accessor will warn or die by calling Carp::carp | ||||
| 455 | or Carp::croak. If you don't like this you can override _carp() and _croak() in | ||||
| 456 | your subclass and do whatever else you want. | ||||
| 457 | |||||
| 458 | =cut | ||||
| 459 | |||||
| 460 | 3 | 297µs | use Carp (); | ||
| 461 | |||||
| 462 | sub _carp { | ||||
| 463 | my ($self, $msg) = @_; | ||||
| 464 | Carp::carp($msg || $self); | ||||
| 465 | return; | ||||
| 466 | } | ||||
| 467 | |||||
| 468 | sub _croak { | ||||
| 469 | my ($self, $msg) = @_; | ||||
| 470 | Carp::croak($msg || $self); | ||||
| 471 | return; | ||||
| 472 | } | ||||
| 473 | |||||
| 474 | =head1 EFFICIENCY | ||||
| 475 | |||||
| 476 | Class::Accessor does not employ an autoloader, thus it is much faster | ||||
| 477 | than you'd think. Its generated methods incur no special penalty over | ||||
| 478 | ones you'd write yourself. | ||||
| 479 | |||||
| 480 | Here are Schwern's results of benchmarking Class::Accessor, | ||||
| 481 | Class::Accessor::Fast, a hand-written accessor, and direct hash access. | ||||
| 482 | |||||
| 483 | Benchmark: timing 500000 iterations of By Hand - get, By Hand - set, | ||||
| 484 | C::A - get, C::A - set, C::A::Fast - get, C::A::Fast - set, | ||||
| 485 | Direct - get, Direct - set... | ||||
| 486 | |||||
| 487 | By Hand - get: 4 wallclock secs ( 5.09 usr + 0.00 sys = 5.09 CPU) | ||||
| 488 | @ 98231.83/s (n=500000) | ||||
| 489 | By Hand - set: 5 wallclock secs ( 6.06 usr + 0.00 sys = 6.06 CPU) | ||||
| 490 | @ 82508.25/s (n=500000) | ||||
| 491 | C::A - get: 9 wallclock secs ( 9.83 usr + 0.01 sys = 9.84 CPU) | ||||
| 492 | @ 50813.01/s (n=500000) | ||||
| 493 | C::A - set: 11 wallclock secs ( 9.95 usr + 0.00 sys = 9.95 CPU) | ||||
| 494 | @ 50251.26/s (n=500000) | ||||
| 495 | C::A::Fast - get: 6 wallclock secs ( 4.88 usr + 0.00 sys = 4.88 CPU) | ||||
| 496 | @ 102459.02/s (n=500000) | ||||
| 497 | C::A::Fast - set: 6 wallclock secs ( 5.83 usr + 0.00 sys = 5.83 CPU) | ||||
| 498 | @ 85763.29/s (n=500000) | ||||
| 499 | Direct - get: 0 wallclock secs ( 0.89 usr + 0.00 sys = 0.89 CPU) | ||||
| 500 | @ 561797.75/s (n=500000) | ||||
| 501 | Direct - set: 2 wallclock secs ( 0.87 usr + 0.00 sys = 0.87 CPU) | ||||
| 502 | @ 574712.64/s (n=500000) | ||||
| 503 | |||||
| 504 | So Class::Accessor::Fast is just as fast as one you'd write yourself | ||||
| 505 | while Class::Accessor is twice as slow, a price paid for flexibility. | ||||
| 506 | Direct hash access is about six times faster, but provides no | ||||
| 507 | encapsulation and no flexibility. | ||||
| 508 | |||||
| 509 | Of course, its not as simple as saying "Class::Accessor is twice as | ||||
| 510 | slow as one you write yourself". These are benchmarks for the | ||||
| 511 | simplest possible accessor, if your accessors do any sort of | ||||
| 512 | complicated work (such as talking to a database or writing to a file) | ||||
| 513 | the time spent doing that work will quickly swamp the time spend just | ||||
| 514 | calling the accessor. In that case, Class::Accessor and the ones you | ||||
| 515 | write will tend to be just as fast. | ||||
| 516 | |||||
| 517 | |||||
| 518 | =head1 EXAMPLES | ||||
| 519 | |||||
| 520 | Here's an example of generating an accessor for every public field of | ||||
| 521 | your class. | ||||
| 522 | |||||
| 523 | package Altoids; | ||||
| 524 | |||||
| 525 | use base qw(Class::Accessor Class::Fields); | ||||
| 526 | use fields qw(curiously strong mints); | ||||
| 527 | Altoids->mk_accessors( Altoids->show_fields('Public') ); | ||||
| 528 | |||||
| 529 | sub new { | ||||
| 530 | my $proto = shift; | ||||
| 531 | my $class = ref $proto || $proto; | ||||
| 532 | return fields::new($class); | ||||
| 533 | } | ||||
| 534 | |||||
| 535 | my Altoids $tin = Altoids->new; | ||||
| 536 | |||||
| 537 | $tin->curiously('Curiouser and curiouser'); | ||||
| 538 | print $tin->{curiously}; # prints 'Curiouser and curiouser' | ||||
| 539 | |||||
| 540 | |||||
| 541 | # Subclassing works, too. | ||||
| 542 | package Mint::Snuff; | ||||
| 543 | use base qw(Altoids); | ||||
| 544 | |||||
| 545 | my Mint::Snuff $pouch = Mint::Snuff->new; | ||||
| 546 | $pouch->strong('Blow your head off!'); | ||||
| 547 | print $pouch->{strong}; # prints 'Blow your head off!' | ||||
| 548 | |||||
| 549 | |||||
| 550 | Here's a simple example of altering the behavior of your accessors. | ||||
| 551 | |||||
| 552 | package Foo; | ||||
| 553 | use base qw(Class::Accessor); | ||||
| 554 | Foo->mk_accessor(qw(this that up down)); | ||||
| 555 | |||||
| 556 | sub get { | ||||
| 557 | my $self = shift; | ||||
| 558 | |||||
| 559 | # Note every time someone gets some data. | ||||
| 560 | print STDERR "Getting @_\n"; | ||||
| 561 | |||||
| 562 | $self->SUPER::get(@_); | ||||
| 563 | } | ||||
| 564 | |||||
| 565 | sub set { | ||||
| 566 | my ($self, $key) = splice(@_, 0, 2); | ||||
| 567 | |||||
| 568 | # Note every time someone sets some data. | ||||
| 569 | print STDERR "Setting $key to @_\n"; | ||||
| 570 | |||||
| 571 | $self->SUPER::set($key, @_); | ||||
| 572 | } | ||||
| 573 | |||||
| 574 | |||||
| 575 | =head1 CAVEATS AND TRICKS | ||||
| 576 | |||||
| 577 | Class::Accessor has to do some internal wackiness to get its | ||||
| 578 | job done quickly and efficiently. Because of this, there's a few | ||||
| 579 | tricks and traps one must know about. | ||||
| 580 | |||||
| 581 | Hey, nothing's perfect. | ||||
| 582 | |||||
| 583 | =head2 Don't make a field called DESTROY | ||||
| 584 | |||||
| 585 | This is bad. Since DESTROY is a magical method it would be bad for us | ||||
| 586 | to define an accessor using that name. Class::Accessor will | ||||
| 587 | carp if you try to use it with a field named "DESTROY". | ||||
| 588 | |||||
| 589 | =head2 Overriding autogenerated accessors | ||||
| 590 | |||||
| 591 | You may want to override the autogenerated accessor with your own, yet | ||||
| 592 | have your custom accessor call the default one. For instance, maybe | ||||
| 593 | you want to have an accessor which checks its input. Normally, one | ||||
| 594 | would expect this to work: | ||||
| 595 | |||||
| 596 | package Foo; | ||||
| 597 | use base qw(Class::Accessor); | ||||
| 598 | Foo->mk_accessors(qw(email this that whatever)); | ||||
| 599 | |||||
| 600 | # Only accept addresses which look valid. | ||||
| 601 | sub email { | ||||
| 602 | my($self) = shift; | ||||
| 603 | my($email) = @_; | ||||
| 604 | |||||
| 605 | if( @_ ) { # Setting | ||||
| 606 | require Email::Valid; | ||||
| 607 | unless( Email::Valid->address($email) ) { | ||||
| 608 | carp("$email doesn't look like a valid address."); | ||||
| 609 | return; | ||||
| 610 | } | ||||
| 611 | } | ||||
| 612 | |||||
| 613 | return $self->SUPER::email(@_); | ||||
| 614 | } | ||||
| 615 | |||||
| 616 | There's a subtle problem in the last example, and its in this line: | ||||
| 617 | |||||
| 618 | return $self->SUPER::email(@_); | ||||
| 619 | |||||
| 620 | If we look at how Foo was defined, it called mk_accessors() which | ||||
| 621 | stuck email() right into Foo's namespace. There *is* no | ||||
| 622 | SUPER::email() to delegate to! Two ways around this... first is to | ||||
| 623 | make a "pure" base class for Foo. This pure class will generate the | ||||
| 624 | accessors and provide the necessary super class for Foo to use: | ||||
| 625 | |||||
| 626 | package Pure::Organic::Foo; | ||||
| 627 | use base qw(Class::Accessor); | ||||
| 628 | Pure::Organic::Foo->mk_accessors(qw(email this that whatever)); | ||||
| 629 | |||||
| 630 | package Foo; | ||||
| 631 | use base qw(Pure::Organic::Foo); | ||||
| 632 | |||||
| 633 | And now Foo::email() can override the generated | ||||
| 634 | Pure::Organic::Foo::email() and use it as SUPER::email(). | ||||
| 635 | |||||
| 636 | This is probably the most obvious solution to everyone but me. | ||||
| 637 | Instead, what first made sense to me was for mk_accessors() to define | ||||
| 638 | an alias of email(), _email_accessor(). Using this solution, | ||||
| 639 | Foo::email() would be written with: | ||||
| 640 | |||||
| 641 | return $self->_email_accessor(@_); | ||||
| 642 | |||||
| 643 | instead of the expected SUPER::email(). | ||||
| 644 | |||||
| 645 | |||||
| 646 | =head1 AUTHORS | ||||
| 647 | |||||
| 648 | Copyright 2005 Marty Pauley <marty+perl@kasei.com> | ||||
| 649 | |||||
| 650 | This program is free software; you can redistribute it and/or modify it under | ||||
| 651 | the same terms as Perl itself. That means either (a) the GNU General Public | ||||
| 652 | License or (b) the Artistic License. | ||||
| 653 | |||||
| 654 | =head2 ORIGINAL AUTHOR | ||||
| 655 | |||||
| 656 | Michael G Schwern <schwern@pobox.com> | ||||
| 657 | |||||
| 658 | =head2 THANKS | ||||
| 659 | |||||
| 660 | Liz, for performance tweaks. | ||||
| 661 | |||||
| 662 | Tels, for his big feature request/bug report. | ||||
| 663 | |||||
| 664 | |||||
| 665 | =head1 SEE ALSO | ||||
| 666 | |||||
| 667 | L<Class::Accessor::Fast> | ||||
| 668 | |||||
| 669 | These are some modules which do similar things in different ways | ||||
| 670 | L<Class::Struct>, L<Class::Methodmaker>, L<Class::Generate>, | ||||
| 671 | L<Class::Class>, L<Class::Contract> | ||||
| 672 | |||||
| 673 | L<Class::DBI> for an example of this module in use. | ||||
| 674 | |||||
| 675 | =cut | ||||
| 676 | |||||
| 677 | 1 | 12µs | 1; |