Object::Accessor(3pm)

✨ Object::Accessor ✨

okay bestie, gather round πŸ’– this is the manual page for Object::Accessor, the Perl module that lets you make accessors per object instead of per class. it's giving builder-pattern energy, it's giving "my object has its own lil set of named attributes", and honestly? iconic. let's get into it πŸ¦‹


🌸 NAME 🌸

Object::Accessor β€” interface to create per object accessors


πŸŽ€ SYNOPSIS πŸŽ€

no cap, just look at it:

### using the object
$obj = Object::Accessor->new;        # create object
$obj = Object::Accessor->new(@list); # create object with accessors
$obj = Object::Accessor->new(\%h);   # create object with accessors
                                     # and their allow handlers

$bool   = $obj->mk_accessors('foo'); # create accessors
$bool   = $obj->mk_accessors(        # create accessors with input
           {foo => ALLOW_HANDLER} ); # validation

$bool   = $obj->mk_aliases(          # create an alias to an existing
            alias_name => 'method'); # method name

$clone  = $obj->mk_clone;            # create a clone of original
                                     # object without data
$bool   = $obj->mk_flush;            # clean out all data

@list   = $obj->ls_accessors;        # retrieves a list of all
                                     # accessors for this object

$bar    = $obj->foo('bar');          # set 'foo' to 'bar'
$bar    = $obj->foo();               # retrieve 'bar' again

$sub    = $obj->can('foo');          # retrieve coderef for
                                     # 'foo' accessor
$bar    = $sub->('bar');             # set 'foo' via coderef
$bar    = $sub->();                  # retrieve 'bar' by coderef

### using the object as base class
package My::Class;
use base 'Object::Accessor';

$obj    = My::Class->new;               # create base object
$bool   = $obj->mk_accessors('foo');    # create accessors, etc...

### make all attempted access to non-existent accessors fatal
### (defaults to false)
$Object::Accessor::FATAL = 1;

### enable debugging
$Object::Accessor::DEBUG = 1;

### advanced usage -- callbacks
{   my $obj = Object::Accessor->new('foo');
    $obj->register_callback( sub { ... } );

    $obj->foo( 1 ); # these calls invoke the callback you registered
    $obj->foo()     # which allows you to change the get/set
                    # behaviour and what is returned to the caller.
}

### advanced usage -- lvalue attributes
{   my $obj = Object::Accessor::Lvalue->new('foo');
    print $obj->foo = 1;            # will print 1
}

### advanced usage -- scoped attribute values
{   my $obj = Object::Accessor->new('foo');

    $obj->foo( 1 );
    print $obj->foo;                # will print 1

    ### bind the scope of the value of attribute 'foo'
    ### to the scope of '$x' -- when $x goes out of
    ### scope, 'foo's previous value will be restored
    {   $obj->foo( 2 => \my $x );
        print $obj->foo, ' ', $x;   # will print '2 2'
    }
    print $obj->foo;                # will print 1
}

πŸ’… DESCRIPTION πŸ’…

so, Object::Accessor gives you an interface to create accessors that live per object β€” not per "Class", which is what, for example, Class::Accessor does. different vibe entirely, iykyk ✨

you've got two whole routes you can take:

  • subclass this module and use its accessors straight up on your own module, or
  • store an Object::Accessor object inside your own object and grab the accessors from there.

either way, bestie, there are examples in the SYNOPSIS above πŸ’–


πŸ‘‘ METHODS πŸ‘‘

πŸ¦‹ $object = Object::Accessor->new( [ARGS] );

makes a brand new (and empty, so like. a blank slate, main character origin story) Object::Accessor object. this method is inheritable, so it passes down the family line, no problem.

whatever args you hand to new get passed straight to mk_accessors. no detours, no small talk.

if you want to be able to assign to your accessors as if they were lvalues, then you should create your object in the Object::Accessor::Lvalue namespace instead. peep the LVALUE ACCESSORS section further down for the tea πŸ“


🌈 $bool = $object->mk_accessors( @ACCESSORS | \%ACCESSOR_MAP );

creates a list of accessors for this object β€” and like, NOT for other ones in the same class! this is personal, not communal. also it will not clobber existing data, so if an accessor already exists, asking to create it again is effectively a "no-op". it's fine, it's already cute, we move on πŸ’…

when you pass a hashref as the argument instead of a normal list, you can specify a list of key/value pairs of accessors and their respective input validators. the validators can be anything that Params::Check's allow function accepts β€” go read that manpage for the details, bestie 🫢

for example:

$object->mk_accessors( {
    foo     => qr/^\d+$/,       # digits only
    bar     => [0,1],           # booleans
    zot     => \&my_sub         # a custom verification sub
} );

returns true on success, false on failure. simple as 🌸

accessors that are called on an object but don't exist return undef by default. but β€” and this is the plot twist β€” you can make that a fatal error by setting the global variable $FATAL to true. the GLOBAL VARIABLES section has the details, go look πŸ‘€

note that you can bind the values of attributes to a scope. this lets you "temporarily" change a value of an attribute and have its original value restored up on the end of its bound variable's scope. it's like a lil time-out for your data, and honestly? obsessed 😭

for example, in this snippet of code, the attribute foo will temporarily be set to 2, until the end of the scope of $x, at which point the original value of 1 will be restored:

my $obj = Object::Accessor->new;

$obj->mk_accessors('foo');
$obj->foo( 1 );
print $obj->foo;                # will print 1

### bind the scope of the value of attribute 'foo'
### to the scope of '$x' -- when $x goes out of
### scope, 'foo' previous value will be restored
{   $obj->foo( 2 => \my $x );
    print $obj->foo, ' ', $x;   # will print '2 2'
}
print $obj->foo;                # will print 1

note that all accessors are read/write for everyone. everyone!! see the TODO section for details.


⭐ @list = $self->ls_accessors;

returns a list of accessors that are supported by the current object. want the corresponding coderefs? just pass this list one by one to the can method. easy πŸŽ€


πŸ’œ $ref = $self->ls_allow(KEY)

returns the allow handler for the given key, which you can use with Params::Check's allow() handler. and if there was no allow handler specified? you get an allow handler that always returns true. generous. supportive. the friend we all deserve 🫢


🧚 $bool = $self->mk_aliases( alias => method, [alias2 => method2, ...] );

creates an alias for a given method name. for all intents and purposes, these two accessors are now identical for this object β€” like twinning fr fr πŸ‘―β€β™€οΈ it's akin to doing the following on the symbol table level:

*alias = *method

this lets you do the following:

$self->mk_accessors('foo');
$self->mk_aliases( bar => 'foo' );

$self->bar( 42 );
print $self->foo;     # will print 42

πŸ“ $clone = $self->mk_clone;

makes a clone of the current object, which will have the exact same accessors as the current object, but without the data stored in them. a fresh-faced copy with no baggage. we love a clean start ✨


πŸ”₯ $bool = $self->mk_flush;

flushes all the data from the current object β€” every accessor gets set back to its default state of undef. it's a hard reset, it's a glow-up, it's a fresh start πŸ’…

returns true on success and false on failure.


🌸 $bool = $self->mk_verify;

checks if all values in the current object are in accordance with their own allow handler. specifically useful to check if an empty initialised object has been filled with values satisfying their own allow criteria. it's the vibe check method, literally πŸ¦‹


πŸŽ€ $bool = $self->register_callback( sub { ... } );

this method lets you register a callback that gets invoked every time an accessor is called. this is your moment to munge input data, access external data stores, etc. β€” go off, bestie πŸ‘‘

you're free to return whatever you wish. and on a set call, the data is even stored in the object. slay.

below is an example of the use of a callback:

$object->some_method( "some_value" );

my $callback = sub {
    my $self    = shift; # the object
    my $meth    = shift; # "some_method"
    my $val     = shift; # ["some_value"]
                         # could be undef -- check 'exists';
                         # if scalar @$val is empty, it was a 'get'

    # your code here

    return $new_val;     # the value you want to be set/returned
}

to access the values stored in the object circumventing the callback structure, you should use the ___get and ___set methods documented further down. sneaky but legal 😌


πŸ’– $bool = $self->can( METHOD_NAME )

this method overrides UNIVERAL::can in order to provide coderefs to accessors which are loaded on demand. it'll behave just like UNIVERSAL::can where it can β€” returning a class method if it exists, or a closure pointing to a valid accessor of this particular object. best of both worlds, no cap.

you can use it as follows:

$sub = $object->can('some_accessor');   # retrieve the coderef
$sub->('foo');                          # 'some_accessor' now set
                                        # to 'foo' for $object
$foo = $sub->();                        # retrieve the contents
                                        # of 'some_accessor'

see the SYNOPSIS for more examples πŸ’œ


πŸ¦‹ $val = $self->___get( METHOD_NAME );

method to directly access the value of the given accessor in the object. it circumvents all calls to allow checks, callbacks, etc. bypassing the whole security line like it owns the place 😭

use only if you "Know What You Are Doing"! general usage for this functionality would be in your own custom callbacks.

🌈 $bool = $self->___set( METHOD_NAME => VALUE );

method to directly set the value of the given accessor in the object. it circumvents all calls to allow checks, callbacks, etc. again with the shortcuts πŸ™ˆ

use only if you "Know What You Are Doing"! general usage for this functionality would be in your own custom callbacks.

πŸ’… $bool = $self->___alias( ALIAS => METHOD );

method to directly alias one accessor to another for this object. it circumvents all sanity checks, etc. literally skipping the whole queue πŸ’€

use only if you "Know What You Are Doing"!

πŸ’… LVALUE ACCESSORS πŸ’…

okay so Object::Accessor ALSO supports lvalue attributes, and that's kind of a big deal. but you can't just get them by default β€” you have to build your objects in the special designated namespace, Object::Accessor::Lvalue. like, the ✨VIP lounge✨ of namespaces. for example:

my $obj = Object::Accessor::Lvalue->new('foo');
$obj->foo += 1;
print $obj->foo;

that will actually print 1 and work exactly as expected, bestie. but since this is an optional feature and it's genuinely not what everyone wants, we make you explicitly opt in by using the Object::Accessor::Lvalue class. no sneaky defaults here πŸŽ€

doing the same thing on the standard Object">Accessor> class would generate the following code & errors:

my $obj = Object::Accessor->new('foo');
$obj->foo += 1;

Can't modify non-lvalue subroutine call

so yeah. it just refuses πŸ’€ no lvalue privileges for you.

also important: lvalue support on AUTOLOAD routines is a perl 5.8.x feature. see perldoc perl58delta for details. (iykyk, ancient lore πŸ¦‹)

⚠️ CAVEATS ⚠️

  • Allow handlers β€” because of the whole nature of lvalue subs, we never get access to the value you're assigning, so we literally can not check it against your allow handler. Allow handlers are therefore unsupported under lvalue conditions. periodt. see perldoc perlsub for details. 😭
  • Callbacks β€” again, lvalue subs being lvalue subs, we never get access to the value you are assigning, so we can not provide this value to your callback. and on top of that? we can't even distinguish between a get and a set call. Callbacks are therefore unsupported under lvalue conditions. see perldoc perlsub for details. πŸ™ˆ

🌈 GLOBAL VARIABLES 🌈

πŸ‘‘ $Object::Accessor::FATAL

set this variable to true and every single attempted access to a non-existent accessor becomes FATAL. dramatic. iconic. defaults to false.

πŸ”₯ $Object::Accessor::DEBUG

set this variable to turn on debugging output. defaults to false.


πŸ’­ TODO πŸ’­

Create read-only accessors

rn all accessors are read/write for everyone. the idea is that maybe a future release should make it possible to have read-only accessors too. manifesting that βœ¨πŸ•―οΈ


🚨 CAVEATS 🚨

listen up bestie, this part matters 🫢

if you use codereferences for your allow handlers, you will not be able to freeze the data structures using Storable.

and due to a bug in storable (until at least version 2.15), qr// compiled regexes also don't de-serialize properly. this bug has been reported, but you should be aware of this issue when serializing your objects. ngl, be careful out there πŸŽ€

you can track the bug here:

http://rt.cpan.org/Ticket/Display.html?id=1827

πŸ› BUG REPORTS πŸ›

please report bugs or other issues to <bug-object-accessor@rt.cpan.org>.


🌸 AUTHOR 🌸

this module by Jos Boumans <kane@cpan.org>. king behavior, honestly πŸ‘‘


this library is free software; you may redistribute and/or modify it under the same terms as Perl itself.


aaaand that's a wrap on the whole page, bestie πŸŽ‰ this was perl v5.40.1, dated 2025-05-04, and you just read Object::Accessor(3pm). go forth and accessor responsibly πŸ’…βœ¨

πŸ“¦ where this page comes from