LearnAI ToolsCareerPractice BuildsPlayContact
Lesson 2419 min read

Object-Oriented Perl

Learn how Perl implements object-oriented programming using packages as classes, bless, conventional new constructors, and method calls with ->.

Introduction

Perl's object-oriented programming (OOP) system looks different from what you might have seen in languages like Java or Python, because Perl builds OOP out of simpler pieces you already know: packages, references, and hashes. Understanding these building blocks demystifies Perl OOP and makes even modern, higher-level tools like Moo and Moose easier to understand later.

What You Will Learn
  • How a package doubles as a class definition in Perl.
  • What bless does and why it matters.
  • How to write a conventional new constructor.
  • How to define and call methods using the arrow operator.

Packages as Classes

In Perl, a package is simply a named namespace for variables and subroutines. Classic Perl OOP uses a package as a class: the package name becomes the class name, and subroutines defined within it become that class's methods.

package Dog;
use strict;
use warnings;
sub bark {
print "Woof!\n";
}
1;

On its own, this is just a namespace with one subroutine in it — nothing object-oriented is happening yet. What turns a plain data structure into an "object" of this class is the bless function.

The bless Function

bless takes a reference (almost always a hash reference, used to store the object's data) and associates it with a package name, turning it into an "object" of that class. From that point on, Perl knows which package to look in when you call a method on that reference.

package Dog;
use strict;
use warnings;
sub bark {
my ($self) = @_;
print "$self->{name} says Woof!\n";
}
1;
# File: main.pl
use strict;
use warnings;
use Dog;
my $data = { name => 'Rex' };
my $rex = bless($data, 'Dog');
$rex->bark();
print ref($rex), "\n";
Program Output

Click Run to see what this code prints.

ref($rex) now returns "Dog" instead of "HASH", because bless has tagged this reference as belonging to the Dog class. This is exactly what lets $rex->bark() know to look for the bark subroutine inside the Dog package.

Writing a Constructor

Perl has no dedicated constructor syntax — by convention, classes define a subroutine named new that creates the underlying hash reference, blesses it, and returns it. This convention is followed so consistently across the Perl ecosystem that it is effectively a rule.

package Dog;
use strict;
use warnings;
sub new {
my ($class, %args) = @_;
my $self = {
name => $args{name} // 'Unnamed',
breed => $args{breed} // 'Unknown',
};
return bless($self, $class);
}
sub bark {
my ($self) = @_;
print "$self->{name} the $self->{breed} says Woof!\n";
}
1;
# File: main.pl
use strict;
use warnings;
use Dog;
my $rex = Dog->new(name => 'Rex', breed => 'Labrador');
$rex->bark();
Program Output

Click Run to see what this code prints.

Why $class Instead of "Dog"?

Using bless($self, $class) instead of hard-coding bless($self, 'Dog') lets subclasses that inherit from Dog reuse this same constructor correctly, blessing the object into the subclass's name instead.

Defining Methods

A method is just a regular subroutine defined inside the class's package, with one convention: the first argument it receives is always the object (or the class name, for a constructor) it was called on. By convention, this first argument is unpacked into a variable named $self.

package Dog;
use strict;
use warnings;
sub new {
my ($class, %args) = @_;
my $self = { name => $args{name} // 'Unnamed', energy => 100 };
return bless($self, $class);
}
sub bark {
my ($self) = @_;
$self->{energy} -= 5;
print "$self->{name} barks! (energy: $self->{energy})\n";
}
sub rest {
my ($self) = @_;
$self->{energy} += 20;
print "$self->{name} rests. (energy: $self->{energy})\n";
}
1;
use strict;
use warnings;
use Dog;
my $rex = Dog->new(name => 'Rex');
$rex->bark();
$rex->bark();
$rex->rest();
Program Output

Click Run to see what this code prints.

Calling Methods With ->

The arrow operator (->) is used to call a method on an object, exactly the same arrow used earlier to dereference hash and array references. Perl uses the object's blessed class to look up which package's subroutine to run, automatically passing the object itself as the first argument.

use strict;
use warnings;
use Dog;
my $rex = Dog->new(name => 'Rex');
# These two calls are equivalent:
$rex->bark();
Dog::bark($rex);
Program Output

Click Run to see what this code prints.

Prefer -> Over Direct Package Calls

Dog::bark($rex) is shown above only to illustrate what -> is doing under the hood. Always call methods with -> in real code — it correctly handles inheritance, while calling the package subroutine directly does not.

Inheritance Basics

A class can inherit methods from another class using the parent pragma (or the older use base). If a subclass does not define its own version of a method, Perl automatically looks it up in the parent class instead.

package Animal;
use strict;
use warnings;
sub new {
my ($class, %args) = @_;
my $self = { name => $args{name} // 'Unnamed' };
return bless($self, $class);
}
sub speak {
my ($self) = @_;
print "$self->{name} makes a sound.\n";
}
1;
package Cat;
use strict;
use warnings;
use parent -norequire, 'Animal';
sub speak {
my ($self) = @_;
print "$self->{name} says Meow!\n";
}
1;
use strict;
use warnings;
use Animal;
use Cat;
my $generic = Animal->new(name => 'Generic Animal');
my $cat = Cat->new(name => 'Whiskers');
$generic->speak();
$cat->speak();
Program Output

Click Run to see what this code prints.

Cat inherits the new constructor directly from Animal (it does not redefine it), but overrides speak with its own version. This is the classic OOP concept of method overriding, implemented here with nothing more exotic than packages, bless, and inheritance via parent.

Common Mistakes

Avoid These Mistakes
  • Forgetting to unpack $self as the first argument in every method — it is always @_[0], not automatically available.
  • Hard-coding the class name in bless($self, 'Dog') instead of bless($self, $class), which breaks correct behavior for subclasses.
  • Calling a package subroutine directly (Dog::bark($rex)) instead of using -> , which silently breaks inheritance and polymorphism.
  • Forgetting the trailing 1; at the end of a class file, so use fails to load it.
  • Confusing the constructor naming convention (new) with an actual language keyword — Perl does not require it to be called new, but virtually every module follows this convention.

Best Practices

  • Always use bless($self, $class), not a hard-coded class name, so subclassing works correctly.
  • Follow the new() constructor convention so your classes behave predictably for anyone reading your code.
  • Always call methods with the arrow operator (->), never by calling the package subroutine directly.
  • For any new, real-world project, consider a modern OOP layer like Moo instead of hand-rolled bless-based classes — it removes most of this boilerplate while still compiling down to the same fundamentals.
  • Keep each class in its own module file, with the filename matching the package name (Dog.pm for package Dog).

Frequently Asked Questions

Not built into the language the way Java has a class keyword. Classic Perl OOP simulates classes using packages, blessed references, and convention. Newer Perl versions (5.38+) are introducing an experimental, more formal class feature, but bless-based OOP remains the classic and most widely deployed approach.

It attaches a class name to a reference so Perl knows which package to search when a method is called on it via ->. The underlying data (usually a hash) is otherwise unchanged.

A hash reference lets each object property be accessed by name ($self->{name}) rather than a numeric position, which is far more readable and resilient to future changes than an array reference would be.

For real projects, generally yes — they eliminate repetitive boilerplate (constructors, accessors, type checking) while compiling down to the same bless-based foundation you just learned, which is why understanding this lesson matters even if you use Moo later.

Key Takeaways

  • A Perl class is conventionally a package containing subroutines that act as methods.
  • bless($ref, $class) associates a reference (usually a hash reference) with a class name, turning it into an object.
  • By strong convention, a class defines a new subroutine as its constructor, returning a blessed reference.
  • Methods are called with the arrow operator (->), which passes the object as the first argument automatically.
  • The parent pragma implements inheritance, letting a subclass reuse or override its parent's methods.

Summary

Object-oriented Perl builds classes and objects out of the same fundamentals you already know — packages, references, and hashes — wrapped up with the bless function. With this foundation in place, you are ready to make your programs more robust by handling things that can go wrong, which is exactly what the next lesson on error handling with eval and die covers.

Next Lesson →

Error Handling (eval & die)