Skip to content

Perl Object Oriented

Perl supports object-oriented programming. Its OO system is flexible and based on packages, references, and a special function called bless. While Perl’s built-in OO is powerful, modern Perl often utilizes systems like Moo, Moose, or Object::Pad for more features and syntactic sugar.

  • Object: An object in Perl is simply a reference (usually to a hash or an array) that has been “blessed” into a class. Blessing associates the reference with a package name, making it an instance of that class.
  • Class: A class in Perl is a package. This package contains the methods (subroutines) that operate on objects of that class.
  • Method: A method is a subroutine defined within a class (package). The first argument to a method is always the object itself (if called on an object, e.g., $obj->method()) or the class name (if called as a class method, e.g., ClassName->method()). This first argument is often called the “invocant”.
  • Blessing: The bless function is used to turn a regular reference into an object. bless $reference, $className; associates $reference with $className.

A class is defined using the package keyword. Methods are subroutines within this package.

# File: Person.pm
package Person;
use strict;
use warnings;
# Constructor
sub new {
my ($class, %args) = @_;
my $self = {
firstName => $args{firstName} // 'N/A', # Using defined-or for defaults
lastName => $args{lastName} // 'N/A',
ssn => $args{ssn} // '000-00-0000',
};
bless $self, $class; # Make $self an object of class $class (Person)
return $self;
}
# Accessor method (getter)
sub get_full_name {
my ($self) = @_;
return $self->{firstName} . " " . $self->{lastName};
}
# Mutator method (setter)
sub set_ssn {
my ($self, $new_ssn) = @_;
if (defined $new_ssn) {
# Basic validation could go here
$self->{ssn} = $new_ssn;
}
return $self->{ssn};
}
1; # Modules must return a true value

Creating and Using Objects (Instantiation)

Section titled “Creating and Using Objects (Instantiation)”

To create an instance of a class (an object), you call its constructor method, conventionally named new.

#!/usr/bin/env perl
use strict;
use warnings;
use FindBin qw($Bin); # To find the script's directory
use lib $Bin; # Add it to @INC to find Person.pm
use Person; # Load the Person class
# Create a Person object
my $person1 = Person->new(
firstName => "Jane",
lastName => "Doe",
ssn => "123-45-6789"
);
# Call methods on the object
print "Person 1: ", $person1->get_full_name(), "\n";
print "Person 1 SSN (initial): ", $person1->{ssn}, "\n"; # Direct access (discouraged for encapsulation)
$person1->set_ssn("987-65-4321");
print "Person 1 SSN (updated): ", $person1->{ssn}, "\n";
my $person2 = Person->new(firstName => "John");
print "Person 2: ", $person2->get_full_name(), " (SSN: ", $person2->{ssn}, ")\n";

Output of the script:

Person 1: Jane Doe
Person 1 SSN (initial): 123-45-6789
Person 1 SSN (updated): 987-65-4321
Person 2: John N/A (SSN: 000-00-0000)

Perl does not enforce data privacy (e.g., private attributes) in its basic OO system. Object attributes (hash keys in our example) can be accessed directly. However, it’s good practice to use accessor (getter) and mutator (setter) methods to interact with object data. This promotes encapsulation, allowing the internal representation of the object to change without breaking code that uses the class.

In the Person.pm example, get_full_name is a getter, and set_ssn is a setter. Naming attributes with a leading underscore (e.g., _firstName) is a common convention to indicate they are intended for internal use, though Perl doesn’t enforce this.

Inheritance allows a class (subclass or child class) to inherit methods and attributes from another class (superclass or parent class). Perl implements inheritance via the special package array @ISA.

To make a class Employee inherit from Person, you set Employee’s @ISA array:

# File: Employee.pm
package Employee;
use strict;
use warnings;
use Person; # We need the Person class definition
our @ISA = qw(Person); # Employee ISA Person (inherits from Person)
# Constructor for Employee
sub new {
my ($class, %args) = @_;
# Call parent's constructor
my $self = $class->SUPER::new(
firstName => $args{firstName},
lastName => $args{lastName},
ssn => $args{ssn}
);
# Add Employee-specific attributes
$self->{employeeID} = $args{employeeID} // 'EMP-0000';
$self->{department} = $args{department} // 'Unassigned';
# Re-bless into the current class, though SUPER::new already blessed into Person.
# For simple inheritance, this bless might not be strictly necessary if SUPER::new
# handles the class correctly, but often good for clarity or complex hierarchies.
bless $self, $class;
return $self;
}
# Employee-specific method
sub get_employee_details {
my ($self) = @_;
return "ID: " . $self->{employeeID} . ", Name: " . $self->get_full_name() . ", Dept: " . $self->{department};
}
# Method Overriding: Provide a specialized version of a parent method
sub get_full_name {
my ($self) = @_;
# Call parent's get_full_name and append title
my $fullName = $self->SUPER::get_full_name();
return "Emp. " . $fullName;
}
1;

Using the Employee class:

#!/usr/bin/env perl
use strict;
use warnings;
use FindBin qw($Bin);
use lib $Bin;
use Employee;
my $emp1 = Employee->new(
firstName => "Alice",
lastName => "Smith",
ssn => "111-22-3333",
employeeID => "EMP-101",
department => "Engineering"
);
print $emp1->get_employee_details(), "\n";
print "Full name (overridden): ", $emp1->get_full_name(), "\n";
# Calling an inherited method (set_ssn is from Person)
$emp1->set_ssn("444-55-6666");
print "Updated SSN: ", $emp1->{ssn}, "\n";

Output:

ID: EMP-101, Name: Emp. Alice Smith, Dept: Engineering
Full name (overridden): Emp. Alice Smith
Updated SSN: 444-55-6666
  • Perl searches for a method first in the object’s own class.
  • If not found, it searches in the classes listed in @ISA, depth-first, left-to-right.
  • The SUPER:: pseudo-class allows a subclass to call an overridden method in its superclass(es).

A subclass can provide its own implementation of a method that is already defined in its superclass. This is called method overriding. The Employee class above overrides get_full_name from the Person class.

If a method is called on an object (or class) that doesn’t exist in its class or any superclasses, Perl looks for a special method named AUTOLOAD. If defined, AUTOLOAD is called with the original arguments. The fully qualified name of the missing method is available in the package variable $AUTOLOAD.

While AUTOLOAD can be used for tasks like creating methods on the fly, it can make code harder to debug and understand. Use it with caution.

# Inside a class definition
# sub AUTOLOAD {
# my $self = shift;
# my $method_name = $AUTOLOAD;
# $method_name =~ s/.*:://; # Strip package name
# warn "Called undefined method: $method_name\n";
# # ... try to handle it ...
# }

Perl uses automatic garbage collection based on reference counting. When an object is no longer referenced (e.g., its variable goes out of scope and no other references to it exist), Perl reclaims its memory.

If you need to perform specific cleanup actions when an object is about to be destroyed (e.g., closing file handles, releasing resources), you can define a special method named DESTROY. This destructor method is called automatically by Perl just before the object’s memory is reclaimed.

# Inside a class definition (e.g., Person.pm)
# sub DESTROY {
# my ($self) = @_;
# print "Person object '", $self->get_full_name(), "' is being destroyed.\n";
# # ... perform cleanup actions ...
# }
#
# # Example of when DESTROY is called:
# {
# my $scoped_person = Person->new(firstName => "Temp");
# # $scoped_person's DESTROY will be called when it goes out of scope here
# }
#
# my $global_person = Person->new(firstName => "Global");
# undef $global_person; # DESTROY called here
# # Or DESTROY called when script ends if $global_person still exists

While understanding Perl’s built-in OO is important, many modern Perl projects use OO systems available from CPAN, such as:

  • Moo: A lightweight, fast, and modern OO system providing features like attributes, type constraints, and roles, with minimal boilerplate.
  • Moose: A highly comprehensive, post-modern OO system with extensive features, including roles, type systems, introspection, and an ecosystem of extensions. It’s very powerful but can have a higher startup overhead.
  • Object::Pad: A newer system (requires Perl 5.30s) that aims to provide more traditional OO syntax (e.g., class, has, method keywords) and better encapsulation directly in the Perl core syntax via keyword plugins.

These systems address some of the verbosity and limitations of Perl’s basic OO, making OO development more robust and maintainable.