PERLOBJ(1perl)
PERLOBJ β the Perl object reference, bestie edition π
okay so this is perlobj, aka Perl's object reference, and it's the part of the Perl docs that actually explains how objects work under the hood. buckle up π
β¨ NAME β¨
perlobj β Perl object reference. that's it, that's the name, periodt.
πΈ DESCRIPTION πΈ
so this doc is a reference for Perl's object orientation (OO) features, fr fr. if what you actually want is a gentle intro to object-oriented programming in Perl, then bestie you want perlootut instead, okay? this one is the deep dive. π«Ά
and before you can even understand Perl objects, you gotta understand references in Perl first. that's a whole separate thing β go read perlreftut for the details. no cap.
This document describes all of Perl's OO features from the ground up. but real talk: if you're just trying to write some object-oriented code of your own, you're probably better served by one of the object systems from CPAN, which are described over in perlootut. π
If you're looking to write your own object system, or you need to maintain code which implements objects from scratch β then this is your doc, because it explains exactly how Perl does object orientation, every single step. π
There are a few basic principles which define object oriented Perl:
- An object is simply a data structure that knows to which class it belongs.
- A class is simply a package. A class provides methods that expect to operate on objects.
- A method is simply a subroutine that expects a reference to an object (or a package name, for class methods) as the first argument.
let's look at each of these in depth, because they're lowkey the whole vibe. β
π¦ An Object is Simply a Data Structure
Unlike many other languages which support object orientation, Perl does not provide any special syntax for constructing an object. not a single keyword, bestie. Objects are merely Perl data structures (hashes, arrays, scalars, filehandles, etc.) that have been explicitly associated with a particular class.
That explicit association is created by the built-in bless function, which is typically used within the constructor subroutine of the class.
Here is a simple constructor:
package File;
sub new {
my $class = shift;
return bless {}, $class;
}
The name new isn't special. like, at all. we could name our constructor something else entirely:
package File;
sub load {
my $class = shift;
return bless {}, $class;
}
The modern convention for OO modules is to always use new as the name for the constructor, but there is no requirement to do so. Any subroutine that blesses a data structure into a class is a valid constructor in Perl. π
In the previous examples, the {} code creates a reference to an empty anonymous hash. The bless function then takes that reference and associates the hash with the class in $class. In the simplest case, the $class variable will end up containing the string File.
We can also use a variable to store a reference to the data structure that is being blessed as our object:
sub new {
my $class = shift;
my $self = {};
bless $self, $class;
return $self;
}
Once we've blessed the hash referred to by $self we can start calling methods on it. This is useful if you want to put object initialization in its own separate method:
sub new {
my $class = shift;
my $self = {};
bless $self, $class;
$self->_initialize();
return $self;
}
Since the object is also a hash, you can treat it as one, using it to store data associated with the object. Typically, code inside the class can treat the hash as an accessible data structure, while code outside the class should always treat the object as opaque. This is called encapsulation. Encapsulation means that the user of an object does not have to know how it is implemented. The user simply calls documented methods on the object. β¨
β οΈ Note, however, that (unlike most other OO languages) Perl does not ensure or enforce encapsulation in any way. If you want objects to actually be opaque you need to arrange for that yourself. This can be done in a variety of ways, including using "Inside-Out objects" or modules from CPAN.
π Objects Are Blessed; Variables Are Not
When we bless something, we are not blessing the variable which contains a reference to that thing, nor are we blessing the reference that the variable stores; we are blessing the thing that the variable refers to (sometimes known as the referent). This is best demonstrated with this code:
use Scalar::Util 'blessed';
my $foo = {};
my $bar = $foo;
bless $foo, 'Class';
print blessed( $bar ) // 'not blessed'; # prints "Class"
$bar = "some other value";
print blessed( $bar ) // 'not blessed'; # prints "not blessed"
When we call bless on a variable, we are actually blessing the underlying data structure that the variable refers to. We are not blessing the reference itself, nor the variable that contains that reference. That's why the second call to blessed( $bar ) returns false β at that point $bar is no longer storing a reference to an object. it's giving "no thoughts, head empty" π
You will sometimes see older books or documentation mention "blessing a reference" or describe an object as a "blessed reference", but this is incorrect. It isn't the reference that is blessed as an object; it's the thing the reference refers to (i.e., the referent). iykyk π§
π A Class is Simply a Package
Perl does not provide any special syntax for class definitions. A package is simply a namespace containing variables and subroutines. The only difference is that in a class, the subroutines may expect a reference to an object or the name of a class as the first argument. This is purely a matter of convention, so a class may contain both methods and subroutines which don't operate on an object or class. π
Each package contains a special array called @ISA. The @ISA array contains a list of that class's parent classes, if any. This array is examined when Perl does method resolution, which we will cover later.
Calling methods from a package means it must be loaded, of course, so you will often want to load a module and add it to @ISA at the same time. You can do so in a single step using the parent pragma. (In older code you may encounter the base pragma, which is nowadays discouraged except when you have to work with the equally discouraged fields pragma.) β
However the parent classes are set, the package's @ISA variable will contain a list of those parents. This is simply a list of scalars, each of which is a string that corresponds to a package name.
All classes inherit from the UNIVERSAL class implicitly. The UNIVERSAL class is implemented by the Perl core, and provides several default methods, such as isa(), can(), and VERSION(). The "UNIVERSAL" class will never appear in a package's @ISA variable. π
Perl only provides method inheritance as a built-in feature. Attribute inheritance is left up the class to implement. See the "Writing Accessors" section for details.
π A Method is Simply a Subroutine
Perl does not provide any special syntax for defining a method. A method is simply a regular subroutine, and is declared with sub. What makes a method special is that it expects to receive either an object or a class name as its first argument. π«Ά
Perl does provide special syntax for method invocation, the -> operator. We will cover this in more detail later.
Most methods you write will expect to operate on objects:
sub save {
my $self = shift;
open my $fh, '>', $self->path() or die $!;
print {$fh} $self->data() or die $!;
close $fh or die $!;
}
β¨ Method Invocation
Calling a method on an object is written as $object->method.
The left hand side of the method invocation (or arrow) operator is the object (or class name), and the right hand side is the method name.
my $pod = File->new( 'perlobj.pod', $data );
$pod->save();
The -> syntax is also used when dereferencing a reference. It looks like the same operator, but these are two different operations. don't let them fool you π
When you call a method, the thing on the left side of the arrow is passed as the first argument to the method. That means when we call Critter->new(), the new() method receives the string Critter as its first argument. When we call $fred->speak(), the $fred variable is passed as the first argument to speak().
Just as with any Perl subroutine, all of the arguments passed in @_ are aliases to the original argument. This includes the object itself. If you assign directly to $_[0] you will change the contents of the variable that holds the reference to the object. We recommend that you don't do this unless you know exactly what you're doing. π seriously. bestie. don't.
Perl knows what package the method is in by looking at the left side of the arrow. If the left hand side is a package name, it looks for the method in that package. If the left hand side is an object, then Perl looks for the method in the package that the object has been blessed into.
If the left hand side is neither a package name nor an object, then the method call will cause an error, but see the section on "Method Call Variations" for more nuances.
π Inheritance
We already talked about the special @ISA array and the parent pragma.
When a class inherits from another class, any methods defined in the parent class are available to the child class. If you attempt to call a method on an object that isn't defined in its own class, Perl will also look for that method in any parent classes it may have.
package File::MP3;
use parent 'File'; # sets @File::MP3::ISA = ('File');
my $mp3 = File::MP3->new( 'Andvari.mp3', $data );
$mp3->save();
Since we didn't define a save() method in the File::MP3 class, Perl will look at the File::MP3 class's parent classes to find the save() method. If Perl cannot find a save() method anywhere in the inheritance hierarchy, it will die. π
In this case, it finds a save() method in the File class. Note that the object passed to save() in this case is still a File::MP3 object, even though the method is found in the File class. main character energy tbh π
We can override a parent's method in a child class. When we do so, we can still call the parent class's method with the SUPER pseudo-class.
sub save {
my $self = shift;
say 'Prepare to rock';
$self->SUPER::save();
}
The SUPER modifier can only be used for method calls. You can't use it for regular subroutine calls or class methods:
SUPER::save($thing); # FAIL: looks for save() sub in package SUPER
SUPER->save($thing); # FAIL: looks for save() method in class
# SUPER
$thing->SUPER::save(); # Okay: looks for save() method in parent
# classes
like literally only that last one slays, the other two are giving fail π₯
π How SUPER is Resolved
ooh this one's next, bestie β keep reading, we're not done yet π
The SUPER pseudo-class gets resolved from the package where the call is made, not based on the object's class. This is lowkey crucial, okay? Because it means methods at different levels of a deep inheritance hierarchy can each correctly call their own parent methods. π
package A;
sub new {
return bless {}, shift;
}
sub speak {
my $self = shift;
say 'A';
}
package B;
use parent -norequire, 'A';
sub speak {
my $self = shift;
$self->SUPER::speak();
say 'B';
}
package C;
use parent -norequire, 'B';
sub speak {
my $self = shift;
$self->SUPER::speak();
say 'C';
}
my $c = C->new();
$c->speak();
So running this example gives you:
A
B
C
See what happened there? This is the whole demonstration of how SUPER gets resolved. Even though the object is blessed into the C class, the speak() method in the B class can still call SUPER::speak() and it'll correctly look in the parent class of B (aka the class the method call is <emphasis>in</emphasis>), not in the parent class of C (aka the class the object actually belongs to). β¨
There are rare cases where this package-based resolution becomes a problem tho. If you copy a subroutine from one package to another, the SUPER resolution will be done based on the original package. π¬
Multiple Inheritance
Multiple inheritance often screams "design problem" ngl, but Perl will always hand you enough rope to hang yourself with if you ask nicely. πͺ’
To declare multiple parents, you just pass multiple class names to use parent:
package MultiChild;
use parent 'Parent1', 'Parent2';
Method Resolution Order
Method resolution order only matters when you're doing multiple inheritance. For single inheritance, Perl just walks up the inheritance chain to find a method:
Grandparent
|
Parent
|
Child
If we call a method on a Child object and that method isn't defined in the Child class, Perl will look for it in the Parent class and then, if it still needs to, in the Grandparent class. π¦
And if Perl can't find the method in any of those classes? It will die with an error message. π
When a class has multiple parents, the method lookup order gets way more complicated.
By default, Perl does a depth-first left-to-right search for a method. That means it starts with the first parent in the @ISA array, then searches all of its parents, grandparents, etc. If it fails to find the method, it then goes to the next parent in the original class's @ISA array and searches from there.
SharedGreatGrandParent
/ \
PaternalGrandparent MaternalGrandparent
\ /
Father Mother
\ /
Child
So given the diagram above, Perl will search Child, Father, PaternalGrandparent, SharedGreatGrandParent, Mother, and finally MaternalGrandparent. This may be a problem because now we're looking in SharedGreatGrandParent before we've checked all its derived classes (i.e. before we tried Mother and MaternalGrandparent). π
It is possible to ask for a different method resolution order with the mro pragma.
package Child;
use mro 'c3';
use parent 'Father', 'Mother';
This pragma lets you switch to the C3 resolution order. In simple terms, C3 order ensures that shared parent classes are never searched before child classes, so Perl will now search: Child, Father, PaternalGrandparent, Mother, MaternalGrandparent, and finally SharedGreatGrandParent. Note tho that this is not "breadth-first" searching: all the Father ancestors (except the common ancestor) are searched before any of the Mother ancestors are considered. π
The C3 order also lets you call methods in sibling classes with the next pseudo-class. See the mro documentation for more details on this feature. π
Method Resolution Caching
When Perl searches for a method, it caches the lookup so future calls to that method don't need to search for it again. Changing a class's parent class or adding subroutines to a class will invalidate the cache for that class. ποΈ
The mro pragma provides some functions for manipulating the method cache directly.
Writing Constructors
As we mentioned earlier, Perl provides no special constructor syntax. This means a class has to implement its own constructor. A constructor is basically just a class method that returns a reference to a new object. π
The constructor can also accept additional parameters that define the object. Let's write a real constructor for the File class we used earlier:
package File;
sub new {
my $class = shift;
my ( $path, $data ) = @_;
my $self = bless {
path => $path,
data => $data,
}, $class;
return $self;
}
As you can see, we've stored the path and file data in the object itself. Remember bestie, under the hood this object is still just a hash. Later, we'll write accessors to manipulate this data. π
For our File::MP3 class, we can check to make sure that the path we're given ends with .mp3:
package File::MP3;
sub new {
my $class = shift;
my ( $path, $data ) = @_;
die "You cannot create a File::MP3 without an mp3 extension\n"
unless $path =~ /\.mp3\z/;
return $class->SUPER::new(@_);
}
This constructor lets its parent class do the actual object construction. Iconic behavior honestly. β¨
Attributes
An attribute is a piece of data belonging to a particular object. Unlike most object-oriented languages, Perl provides no special syntax or support for declaring and manipulating attributes. It's giving "figure it out yourself" energy. π
Attributes are often stored in the object itself. For example, if the object is an anonymous hash, we can store the attribute values in the hash using the attribute name as the key.
While it's possible to refer directly to these hash keys outside of the class, it's considered a best practice to wrap all access to the attribute with accessor methods. Trust the process. π«Ά
This has several advantages. Accessors make it easier to change the implementation of an object later while still preserving the original API.
An accessor lets you add additional code around attribute access. For example, you could apply a default to an attribute that wasn't set in the constructor, or you could validate that a new value for the attribute is acceptable. Very main character of you. π
Finally, using accessors makes inheritance much simpler. Subclasses can use the accessors rather than having to know how a parent class is implemented internally.
Writing Accessors
As with constructors, Perl provides no special accessor declaration syntax, so classes must provide explicitly written accessor methods. There are two common types of accessors: read-only and read-write. π
A simple read-only accessor just gets the value of a single attribute:
sub path {
my $self = shift;
return $self->{path};
}
A read-write accessor will let the caller set the value and get it:
sub path {
my $self = shift;
if (@_) {
$self->{path} = shift;
}
return $self->{path};
}
An Aside About Smarter and Safer Code
Our constructor and accessors are not very smart ngl. They don't check that a $path is defined, nor do they check that a $path is a valid filesystem path. π
Doing these checks by hand can quickly become tedious. Writing a bunch of accessors by hand is also incredibly tedious. There are a lot of modules on CPAN that can help you write safer and more concise code, including the modules we recommend in perlootut. Go check 'em out bestie! π
Method Call Variations
Perl supports several other ways to call methods besides the $object->method() usage we've seen so far. We love options. π
Method Names with a Fully Qualified Name
Perl lets you call methods using their fully qualified name (the package and method name):
my $mp3 = File::MP3->new( 'Regin.mp3', $data );
$mp3->File::save();
When you call a fully qualified method name like File::save, the method resolution search for the save method starts in the File class, skipping any save method the File::MP3 class may have defined. It still searches the File class's parents if necessary.
While this feature is most commonly used to explicitly call methods inherited from an ancestor class, there is no technical restriction that enforces this:
my $obj = Tree->new();
$obj->Dog::bark();
This calls the bark method from class Dog on an object of class Tree, even if the two classes are completely unrelated. Use this with great care. π¬
The SUPER pseudo-class that was described earlier is not the same as calling a method with a fully-qualified name. See the earlier "Inheritance" section for details.
Method Names as Strings
Perl lets you use a scalar variable containing a string as a method name:
my $file = File->new( $path, $data );
my $method = 'save';
$file->$method();
This works exactly like calling $file->save(). This can be super useful for writing dynamic code. For example, it allows you to pass a method name to be called as a parameter to another method. Slay. π
Class Names as Strings
Perl also lets you use a scalar containing a string as a class name:
my $class = 'File';
my $file = $class->new( $path, $data );
Again, this allows for very dynamic code. β¨
Subroutine References as Methods
You can also use a subroutine reference as a method:
my $sub = sub {
my $self = shift;
$self->save();
};
$file->$sub();
This is exactly equivalent to writing $sub->($file). You may see this idiom in the wild combined with a call to can:
if ( my $meth = $object->can('foo') ) {
$object->$meth();
}
Dereferencing Method Call
Perl also lets you use a dereferenced scalar reference in a method call. That's a mouthful, so let's look at some code:
$file->${ \'save' };
$file->${ returns_scalar_ref() };
$file->${ \( returns_scalar() ) };
$file->${ returns_ref_to_sub_ref() };
This works if the dereference produces a string or a subroutine reference. π§
Method Calls on Filehandles
Under the hood, Perl filehandles are instances of the IO::Handle or IO::File class. Once you have an open filehandle, you can call methods on it. Additionally, you can call methods on the STDIN, STDOUT, and STDERR filehandles. π
open my $fh, '>', 'path/to/file';
$fh->autoflush();
$fh->print('content');
STDOUT->autoflush();
okay bestie, that's the "I want my output NOW, no buffering era" move π autoflush stays undefeated.
β¨ Invoking Class Methods β¨
So here's the tea π« β Perl lets you write package names and subroutine names as barewords, and because of that it sometimes guesses the meaning wrong. Like, Class->new()? Rude of it, but Peri can read that two totally different ways:
'Class'->new()β a method call on the class literally namedClass, orClass()->new()β "call a sub namedClass(), THEN callnew()as a method on whateverClass()handed back."
In English, that second reading is giving "run Class(), take its return value, call new() on it." And if a sub named Class() exists in the current namespace? Perl will always pick option two. Always. No cap. π
So how do you force the first interpretation β a real method call on the class Class? Two ways, bestie:
Way one: slap a :: on the end of the class name.
Class::->new()
Perl will always read this as a method call. Iconic.
Way two: quote the class name.
'Class'->new()
And obviously, if the class name lives in a scalar, Perl does the right thing automatically:
my $class = 'Class';
$class->new();
π Indirect Object Syntax π
Outside of the file handle case, use of this syntax is discouraged because it can confuse the Perl interpreter. More deets below.
Perl also supports another method invocation syntax called "indirect object" notation. It's called "indirect" because β plot twist β the method comes before the object it's being called on. π
It works with any class or object method:
my $file = new File $path, $data;
save $file;
...but we are begging you, pleading with you, to avoid this syntax. Several reasons, let's list them:
- It's confusing to read. In that example above, is
savea method theFileclass provides, or just some plain subroutine that happens to want a file object as its first arg? Nobody knows. π§ - With class methods it's even worse. Because Perl allows sub names written as barewords, it has to guess whether the bareword after the method is a class name or a subroutine name. So Perl could resolve that syntax as either
File->new( $path, $data )ornew( File( $path, $data ) ). Two completely different programs!! - The guessing is a heuristic. To parse it, Perl looks at what package names it's seen, what subroutines exist in the current package, what barewords it's seen before, and other input. Needless to say, heuristics can produce very surprising results π
- Old docs did this, sorry. Older documentation (and some CPAN modules) encouraged this syntax, especially for constructors, so you'll still find it out in the wild. But for new code? Please don't.
You can force Perl to read that bareword as a class name by appending :: to it, exactly like we saw earlier:
my $file = new File:: $path, $data;
Also, indirect object syntax is only available when the indirect named feature is enabled. It's enabled by default, but you can disable it if you ask nicely. It's present in older feature version bundles, but it was removed from the :5.36 bundle β which means a use VERSION declaration of v5.36 or above will disable the feature too. π
use v5.36;
# indirect object syntax is no longer available
πΈ bless, blessed, and ref πΈ
So like we said before, an object is just a data structure that got blessed into a class via the bless function. And bless takes either one or two arguments:
my $object = bless {}, $class;
my $object = bless {};
- In the first form, that anonymous hash is being blessed into the class sitting in
$class. - In the second form, the anonymous hash is blessed into the current package.
The second form is strongly discouraged because it breaks a subclass's ability to reuse the parent's constructor. You'll still run into it in existing code though. π¬
Wanna know if a particular scalar is pointing at an object? Use the blessed function exported by Scalar::Util, which ships with the Perl core:
use Scalar::Util 'blessed';
if ( defined blessed($thing) ) { ... }
If $thing refers to an object, this function returns the name of the package that object was blessed into π If $thing does not hold a reference to a blessed object, blessed returns undef.
β οΈ Heads up:blessed($thing)will also return false if$thinggot blessed into a class literally named"0". It's possible! It's also quite pathological. Don't make a class named"0"unless you know what you're doing.
Similarly, Perl's built-in ref function treats a blessed object reference specially: if you call ref($thing) and $thing holds an object reference, it returns the name of the class the object was blessed into.
But if all you want is "does this variable hold an object reference?", we recommend defined blessed($object) β because ref returns true values for all references, not just objects. β¨
π The UNIVERSAL Class π
Every class automatically inherits from the UNIVERSAL class, which is built right into the Perl core. It hands out a bunch of methods, and every single one can be called on either a class or an object. You can also override some of them in your own class β and if you do, we recommend following the built-in semantics described below. π«Ά
isa($class)
The isa method returns true if the object is a member of the class in $class, or a member of a subclass of $class.
If you override this method, it should never throw an exception.
DOES($role)
The DOES method returns true if its object claims to perform the role $role. By default this is equivalent to isa. It exists for object system extensions that implement roles, like Moose and Role::Tiny. π
You can also override DOES directly in your own classes. And same deal:
If you override this method, it should never throw an exception.
can($method)
The can method checks whether the class or object it was called on has a method named $method. It looks in the class and all of its parents. If the method exists, you get back a reference to the subroutine. If it doesn't, you get undef. π¦
If your class responds to method calls via AUTOLOAD, you may want to overload can so it returns a subroutine reference for the methods your AUTOLOAD handles.
If you override this method, it should never throw an exception.
VERSION($need)
The VERSION method returns the version number of the class (package).
If the $need argument is given, it checks that the current version β as defined by the $VERSION variable in the package β is greater than or equal to $need, and it will die if that's not the case π This method gets called automatically by the VERSION form of use:
use Package 1.2 qw(some imported subs);
# implies:
Package->VERSION(1.2);
We recommend using this method to get another package's version rather than peeking directly at $Package::VERSION β because the package you're looking at could have overridden the VERSION method. π
We also recommend it for checking whether a module has a sufficient version, because the internal implementation uses the version module to make sure different types of version numbers get compared correctly. β¨
π AUTOLOAD π
If you call a method that doesn't exist in a class, Perl throws an error. BUT β if that class, or any of its parent classes, defines an AUTOLOAD method, then that AUTOLOAD method gets called instead. πͺ
AUTOLOAD is called like a regular method, and the caller won't know the difference. Whatever value your AUTOLOAD method returns gets returned to the caller.
The fully qualified name of the method that was called is available in the $AUTOLOAD package global for your class. Since it's a global, if you want to reference it without a package name prefix while under strict 'vars', you have to declare it.
# XXX - this is a terrible way to implement accessors, but it makes
# for a simple example.
our $AUTOLOAD;
sub AUTOLOAD {
my $self = shift;
# Remove qualifier from original method name...
my $called = $AUTOLOAD =~ s/.*:://r;
# Is there an attribute of that name?
die "No such attribute: $called"
unless exists $self->{$called};
# If so, return it...
return $self->{$called};
}
sub DESTROY { } # see below
Without that our $AUTOLOAD declaration, this code will not compile under the strict pragma. π
And like the comment says β this is not a good way to implement accessors. It's slow and way too clever by half. But you may run into it as a way people provided accessors in older Perl code. For actual recommendations on OO coding in Perl, see perlootut. π
If your class does have anAUTOLOADmethod, we strongly recommend you also overridecanin your class. Your overriddencanshould return a subroutine reference for any method yourAUTOLOADresponds to.
π Destructors π
When the last reference to an object goes away, the object is destroyed. If you've got just one reference to an object stored in a lexical scalar, the object dies when that scalar goes out of scope. If you store the object in a package global, that object may not go out of scope until the program exits. πΆπ«οΈ
Wanna do something when the object gets destroyed? Define a DESTROY method in your class. Perl will always call it at the appropriate time β unless the method is empty. (An empty DESTROY? Perl skips it. Sneaky.)
DESTROY gets called just like any other method, with the object as the first argument. It receives no additional arguments. And plot twist: $_[0] will be read-only inside the destructor, so you cannot assign a value to it. π«
If yourDESTROYmethod throws an exception, that will not cause any control transfer beyond exiting the method. The exception gets reported toSTDERRas a warning, marked(in cleanup), and Perl just... carries on with whatever it was doing before. π
Because DESTROY methods can be called at any time, you should localize any global status variables that might get set by anything you do inside your DESTROY method. In doubt about a particular status variable? Localizing it doesn't hurt. There are five global status variables, and the safest move is to localize all five of them:
sub DESTROY {
local($., $@, $!, $^E, $?);
my $self = shift;
...;
}
okay so bestie, real talk: if you define an AUTOLOAD in your class, then Perl will call your AUTOLOAD to handle the DESTROY method. You can prevent this by defining an empty DESTROY, like we did in the autoloading example. You can also check the value of $AUTOLOAD and return without doing anything when called to handle DESTROY. periodt. π
β¨ Global Destruction β¨ π
The order in which objects are destroyed during the global destruction before the program exits is unpredictable. This means that any objects contained by your object may already have been destroyed. You should check that a contained object is defined before calling a method on it:
sub DESTROY {
my $self = shift;
$self->{handle}->close() if $self->{handle};
}
You can use the ${^GLOBAL_PHASE} variable to detect if you are currently in the global destruction phase:
sub DESTROY {
my $self = shift;
return if ${^GLOBAL_PHASE} eq 'DESTRUCT';
$self->{handle}->close();
}
Note that this variable was added in Perl 5.14.0. If you want to detect the global destruction phase on older versions of Perl, you can use the Devel::GlobalDestruction module on CPAN. π
If your DESTROY method issues a warning during global destruction, the Perl interpreter will append the string during global destruction to the warning. (Yes, that leading space is literally part of the string, iykyk. π)
During global destruction, Perl will always garbage collect objects before unblessed references. See PERL_DESTRUCT_LEVEL in perlhacktips for more information about global destruction.
Non-Hash Objects π¦
All the examples so far have shown objects based on a blessed hash. However, it's possible to bless any type of data structure or referent, including scalars, globs, and subroutines. You may see this sort of thing when looking at code in the wild. π
Here's an example of a module as a blessed scalar:
package Time;
use v5.36;
sub new {
my $class = shift;
my $time = time;
return bless \$time, $class;
}
sub epoch {
my $self = shift;
return $$self;
}
my $time = Time->new();
print $time->epoch();
Inside-Out objects πΈ
In the past, the Perl community experimented with a technique called "inside-out objects". An inside-out object stores its data outside of the object's reference, indexed on a unique property of the object, such as its memory address, rather than in the object itself. This has the advantage of enforcing the encapsulation of object attributes, since their data is not stored in the object itself. it's giving encapsulation realness. β¨
This technique was popular for a while (and was recommended in Damian Conway's Perl Best Practices), but never achieved universal adoption. The Object::InsideOut module on CPAN provides a comprehensive implementation of this technique, and you may see it or other inside-out modules in the wild. π§
Here is a simple example of the technique, using the Hash::Util::FieldHash core module. This module was added to the core to support inside-out object implementations.
package Time;
use v5.36;
use Hash::Util::FieldHash 'fieldhash';
fieldhash my %time_for;
sub new {
my $class = shift;
my $self = bless \( my $object ), $class;
$time_for{$self} = time;
return $self;
}
sub epoch {
my $self = shift;
return $time_for{$self};
}
my $time = Time->new;
print $time->epoch;
Pseudo-hashes π
The pseudo-hash feature was an experimental feature introduced in earlier versions of Perl and removed in 5.10.0. A pseudo-hash is an array reference which can be accessed using named keys like a hash. You may run into some code in the wild which uses it. See the fields pragma for more information.
π SEE ALSO π
A kinder, gentler tutorial on object-oriented programming in Perl can be found in perlootut. You should also check out perlmodlib for some style guides on constructing both modules and classes. π«Ά
and that's a wrap on this iconic manpage, bestie. it's from perl v5.44.0, dated 2026-10-17, and yes it's literally PERLOBJ(1perl). now go manifest some beautiful blessed references. π πβ
π¦ where this page comes from
- arch rolling: perl 5.44.0-1 Β· Artistic-1.0-Perl AND GPL-1.0-or-later
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms