package Class::Accessor::Lite; use strict; our $VERSION = '0.06'; use Carp (); sub import { shift; my %args = @_; my $pkg = caller(0); my %key_ctor = ( rw => \&_mk_accessors, ro => \&_mk_ro_accessors, wo => \&_mk_wo_accessors, ); for my $key (sort keys %key_ctor) { if (defined $args{$key}) { Carp::croak "value of the '$key' parameter should be an arrayref" unless ref($args{$key}) eq 'ARRAY'; $key_ctor{$key}->($pkg, @{$args{$key}}); } } _mk_new($pkg) if $args{new}; 1; } sub mk_new_and_accessors { (undef, my @properties) = @_; my $pkg = caller(0); _mk_new($pkg); _mk_accessors($pkg, @properties); } sub mk_new { my $pkg = caller(0); _mk_new($pkg); } sub mk_accessors { (undef, my @properties) = @_; my $pkg = caller(0); _mk_accessors($pkg, @properties); } sub mk_ro_accessors { (undef, my @properties) = @_; my $pkg = caller(0); _mk_ro_accessors($pkg, @properties); } sub mk_wo_accessors { (undef, my @properties) = @_; my $pkg = caller(0); _mk_wo_accessors($pkg, @properties); } sub _mk_new { my $pkg = shift; no strict 'refs'; *{$pkg . '::new'} = __m_new($pkg); } sub _mk_accessors { my $pkg = shift; no strict 'refs'; for my $n (@_) { *{$pkg . '::' . $n} = __m($n); } } sub _mk_ro_accessors { my $pkg = shift; no strict 'refs'; for my $n (@_) { *{$pkg . '::' . $n} = __m_ro($pkg, $n); } } sub _mk_wo_accessors { my $pkg = shift; no strict 'refs'; for my $n (@_) { *{$pkg . '::' . $n} = __m_wo($pkg, $n); } } sub __m_new { my $pkg = shift; no strict 'refs'; return sub { my $klass = shift; bless { (@_ == 1 && ref($_[0]) eq 'HASH' ? %{$_[0]} : @_), }, $klass; }; } sub __m { my $n = shift; sub { return $_[0]->{$n} if @_ == 1; return $_[0]->{$n} = $_[1] if @_ == 2; shift->{$n} = \@_; }; } sub __m_ro { my ($pkg, $n) = @_; sub { if (@_ == 1) { return $_[0]->{$n} if @_ == 1; } else { my $caller = caller(0); Carp::croak("'$caller' cannot access the value of '$n' on objects of class '$pkg'"); } }; } sub __m_wo { my ($pkg, $n) = @_; sub { if (@_ == 1) { my $caller = caller(0); Carp::croak( "'$caller' cannot alter the value of '$n' on objects of class '$pkg'") } else { return $_[0]->{$n} = $_[1] if @_ == 2; shift->{$n} = \@_; } }; } 1; __END__ =head1 NAME Class::Accessor::Lite - a minimalistic variant of Class::Accessor =head1 SYNOPSIS package MyPackage; use Class::Accessor::Lite ( new => 1, rw => [ qw(foo bar) ], ro => [ qw(baz) ], wo => [ qw(hoge) ], ); =head1 DESCRIPTION The module is a variant of C. It is fast and requires less typing, has no dependencies to other modules, and does not mess up the @ISA. =head1 THE USE STATEMENT The use statement (i.e. the C function) of the module takes a single hash as an argument that specifies the types and the names of the properties. Recognises the following keys. =over 4 =item new => $true_or_false the default constructor is created if the value evaluates to true, otherwise nothing is done (the default behaviour) =item rw => \@name_of_the_properties creates a read / write accessor for the name of the properties passed through as an arrayref =item ro => \@name_of_the_properties creates a read-only accessor for the name of the properties passed through as an arrayref =item wo => \@name_of_the_properties creates a write-only accessor for the name of the properties passed through as an arrayref =back For more detailed explanation read the following section describing the behaviour of each function that actually creates the accessors. =head1 FUNCTIONS As of version 0.04 the properties can be specified as the arguments to the C statement (as can be seen in the SYNOPSIS) which is now the recommended way of using the module, but for compatibility the following functions are provided as well. =head2 Class::Accessor::Lite->mk_accessors(@name_of_the_properties) Creates an accessor in current package under the name specified by the arguments that access the properties (of a hashref) with the same name. =head2 Class::Accessor::Lite->mk_ro_accessors(@name_of_the_properties) Same as mk_accessors() except it will generate read-only accessors (i.e. true accessors). If you attempt to set a value with these accessors it will throw an exception. =head2 Class::Accessor::Lite->mk_wo_accessors(@name_of_the_properties) Same as mk_accessors() except it will generate write-only accessors (i.e. mutators). If you attempt to read a value with these accessors it will throw an exception. =head2 Class::Accessor::Lite->mk_new() Creates the C function that accepts a hash or a hashref as the initial properties of the object. =head2 Class::Accessor::Lite->mk_new_and_accessors(@name_of_the_properties) DEPRECATED. Use the new "use Class::Accessor::Lite (...)" style. =head1 FAQ =head2 Can I use C in an inherited module? Yes in most cases, when the class object in the super class is implemented using a hashref. However you _should_ _not_ create the constructor for the inherited class by calling C<new()>> or by C< 1)>>. The only other thing that C does is to set up the accessor functions for given property names through a blessed hashref. =head2 What happens when passing more than one arguments to the accessor? When the accessor built by Class::Accessor::Lite is given more than one arguments, a reference to the arguments will be saved as an arrayref. This behaviour might not be necessary but is implemented as is to maintain compatibility with L. my @data = (1, 2, 3); $obj->someproperty(@data); $obj->someproperty->[2]++; # $data[3] is incremented In general, you should pass an arrayref to set an arrayref to a property. my @data = (1, 2, 3); $obj->someproperty([ @data ]); # save a copy using arrayref $obj->someproper->[2]++; # @data is not modified =head1 SEE ALSO L L =head1 AUTHORS Copyright (C) 2008 - 2010 Kazuho Oku =head1 LICENSE This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.8.6 or, at your option, any later version of Perl 5 you may have available. =cut