Object::Util - a selection of utility methods that can be called on blessed objects
use Object::Util; # $foo might be undef, but this should not die if ($foo->$_isa("Bar")) { ...; }
This module is inspired by Safe::Isa, Object::Tap, and my own OO experiences. It is a hopefully helpful set of methods for working with objects, exposed as lexical coderef variables.
Providing methods as coderefs so that you can do:
$object->$_foo(@args)
... is unusual, so probably requires some explanation.
Firstly some of these methods are designed to be called on either a blessed object or some kind of unblessed reference or value. Calling a method on an unblessed reference like this will croak:
$ref->foo(@args)
Ditto calling methods on undef. Coderefs don't suffer from that problem.
More importantly though, the aim of this module is that these methods should be available for you to call on any object. You can only call $object->foo(@args) if $object's class implements a method called foo, or inherits from a superclass that does. Coderef methods can be called on any object.
$object->foo(@args)
$object
foo
This module adopts the $_foo naming convention pioneered by modules such as Safe::Isa. However (unlike Safe::Isa) the coderefs it provides are true lexical variables (a.k.a. my variables), not package variables (a.k.a. our variables).
$_foo
my
our
$_new
Can be used like $class->$_new(@args) to create a new object. Object::Util will use Module::Runtime to attempt to load $class if it is not already loaded. $class is expected to provide a method called new.
$class->$_new(@args)
$class
new
Can also be used as $factory->$_new(@args) to create a new object, where $factory is a coderef or an object overloading &{}. In this case, $_new will simply call $factory->(@args) and expect that to return an object.
$factory->$_new(@args)
$factory
&{}
$factory->(@args)
$_clone
If the object provides a clone method, calls that. Or if the object appears to be Moose- or Mouse-based, clones it using the metaobject protocol.
clone
Otherwise takes the naive approach of treating the object as a hashref of attribute values, and creates a new object of the same class.
# clone overrides some attributes from the original object my $glenda = $glen->$_clone(name => "Glenda", gender => "f");
That final fallback obviously massively breaks your class' encapsulation, so it should be used sparingly.
$_with_traits
Calling $class->$_with_traits(@traits) will return a new class name that does some extra traits. Should roughly support Moose, Mouse, Moo, and Role::Tiny, though combinations of frameworks (e.g. consuming a Moose role in a Mouse class) will not always work.
$class->$_with_traits(@traits)
If $class is actually a (factory) coderef, then this will only partly work. Example:
my $factory = sub { Foo->new(@_) }; my $instance = $factory->$_with_traits("Bar")->$_new(%args);
The object $instance should now be a Foo object, and should do the Bar role, however if Bar defines any attributes, then $_new will not have initialized them correctly. This is because of the opacity of the $factory: $_with_traits cannot peek inside it and apply traits to the Foo class; instead it needs to build $instance and apply the traits to the already-built object. Therefore any behaviour that Bar defines for the constructor will have been ignored.
$instance
Foo
Bar
It is sometimes possible to work around this issue using:
my $factory = sub { Foo->new(@_) }; my $instance = $factory->$_with_traits("Bar")->$_new(%args); $instance = $instance->$_clone(%args);
$_extend
Calling $object->$_extend(\@traits, \%methods) will add some extra roles and/or methods to an existing object.
$object->$_extend(\@traits, \%methods)
Either @traits or %methods may be omitted. That is, $object->$_extend(\@traits) will add some traits to an existing object but no new methods, and $object->$_extend(\%methods) will add new methods, but no traits. $object->$_extend() also works fine, and is a no-op.
@traits
%methods
$object->$_extend(\@traits)
$object->$_extend(\%methods)
$object->$_extend()
This method always returns $object, which makes it suitable for chaining.
Like Object::Extend, but with added support for roles.
$_murder
Called on an object, tries its best to destroy the object.
my $object = Foo->new; $object->$_murder; defined($object); # false
Not only will $object be set to undef in the above example, but if there were any other references to the object, $_murder will do its best to poison them too.
$_murder will empty out the contents of the underlying hash or array in hashref-based and arrayref-based objects, and for scalarref-based objects will set the underlying scalar to undef.
$_murder will also rebless the reference into a dummy class where all method calls will croak.
$_murder will generously ensure that the object's DESTROY is called before initiating the killing spree, allowing the class to perform any necessary clean-up first.
DESTROY
$_call_if_object
$object->$_call_if_object($method => @args) works like $object->$method(@args), but if $object is undefined, returns undef instead of throwing an exception.
$object->$_call_if_object($method => @args)
$object->$method(@args)
undef
$method may be a method name, or a coderef (anonymous method).
$method
Same as Safe::Isa.
$_try
$object->$_try($method => @args) works like $object->$method(@args), but if any exception is thrown returns undef instead.
$object->$_try($method => @args)
$_tap
$object->$_tap($method => @args) works like $object->$method(@args), but discards the method's return value (indeed it calls the method in void context), and instead returns the object itself, making it useful for chaining.
$object->$_tap($method => @args)
Same as Object::Tap, or the tap method in Ruby.
tap
$_isa
$object->$_isa($class) works like isa as defined in UNIVERSAL, but if $object is undefined, returns false instead of throwing an exception.
$object->$_isa($class)
isa
A shortcut for $object->$_call_if_object(isa => $class).
$object->$_call_if_object(isa => $class)
$_does
$object->$_does($role) works like does as defined in Moose::Object, but if $object is undefined, returns false instead of throwing an exception.
$object->$_does($role)
does
A shortcut for $object->$_call_if_object(does => $role).
$object->$_call_if_object(does => $role)
$_DOES
$object->$_DOES($role) works like DOES as defined in UNIVERSAL, but if $object is undefined, returns false instead of throwing an exception.
$object->$_DOES($role)
DOES
A shortcut for $object->$_call_if_object(DOES => $role).
$object->$_call_if_object(DOES => $role)
$_can
$object->$_can($method) works like can as defined in UNIVERSAL, but if $object is undefined, returns undef instead of throwing an exception.
$object->$_can($method)
can
There is one other significant deviation from the behaviour of UNIVERSAL's can method: $_can also returns true if $method is an unblessed coderef. (The behaviour of $method if it is a blessed object -- particularly in the face of overloading -- can be unintuitive, so is not supported by $_can.)
Similar to Safe::Isa, but not quite the same.
$_dump
Calling $object->$_dump returns a Data::Dumper dump of the object, with some useful changes to the default Data::Dumper output. (Same as Data::Dumper::Concise.)
$object->$_dump
If the object provides its own dump method, this will be called instead. Any additional arguments will be passed through to it.
dump
$_dwarn
Calling $object->$_dwarn(@args) prints a similar dump of the object and any arguments as a warning, then returns the object, so is suitable for tap-like chaining.
$object->$_dwarn(@args)
Unlike $_dump, will not call the object's own dump method.
$_dwarn_call
Calling $object->$_dwarn_call($method, @args) calls the method on the object, passing it the arguments, and returns the result. Along the way, it will dump the object, method, arguments, and return value as warnings. Returns the method's return value.
$object->$_dwarn_call($method, @args)
B::Hooks::Parser is used to inject these methods into your lexical scope, and Internals::SvREADONLY (an internal function built into the Perl core) is used to make them read-only, so you can't do:
Internals::SvREADONLY
use Object::Util; $_isa = sub { "something else" };
If this module detects that B::Hooks::Parser cannot be used on your version of Perl, or your Perl is too old to have Internals::SvREADONLY, then it has various fallback routes, but the variables it provides may end up as package (our) variables, or not be read-only.
If the magic works on your version of Perl, but you wish to avoid the magic anyway, you can switch it off:
use Object::Util magic => 0;
The magic may trigger bugs if you're loading Object::Util in a sufficiently unusual way (for example, require and import instead of use). If this happens, disable magic.
require
import
use
Please report any bugs to http://rt.cpan.org/Dist/Display.html?Queue=Object-Util.
Safe::Isa, UNIVERSAL, Object::Tap, MooseX::Clone, Data::Dumper::Concise, Object::Extend.
Toby Inkster <tobyink@cpan.org>.
This software is copyright (c) 2014, 2018 by Toby Inkster.
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.
THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
To install Object::Util, copy and paste the appropriate command in to your terminal.
cpanm
cpanm Object::Util
CPAN shell
perl -MCPAN -e shell install Object::Util
For more information on module installation, please visit the detailed CPAN module installation guide.