Build and Test a Small Perl Class with bless and Inheritance
You will finish with a small Perl class that constructs an object, stores state, calls an instance method, and inherits a method from a parent class. The examples use Perl v5.38.2, matching the perlobj(1) reference installed on this machine.
The route
Jump straight to the step you need, or tick off Done means at the end.
Allow about fifteen minutes. You need Perl and a shell. Everything below runs as an ordinary user and writes only a temporary script under /tmp; no package installation, service restart or elevated privilege is required.
1. Check the installed Perl
Confirm the interpreter before relying on examples from another Perl release:
$ perl -v
This is perl 5, version 38, subversion 2 (v5.38.2) built for x86_64-linux-gnu-thread-multi
The surrounding text varies between distributions. The useful check is the version number. The local manual is dated 14 September 2026 and identifies itself as part of Perl v5.38.2.
Checkpoint: if perl -v fails, stop here and use the Perl package supplied by your distribution. Do not work around a missing interpreter by copying a module into a system directory.
2. Create a minimal class
Perl has no special class or constructor syntax. A class is a package, and an object is a data structure associated with that package by bless. The conventional constructor name is new, but the name is not magic.
Save this complete example as a temporary file:
$ tmp_perl_object=$(mktemp /tmp/perl-object.XXXXXX)
$ cat > "$tmp_perl_object" <<'PERL'
use strict;
use warnings;
package Counter;
sub new {
my ($class, $start) = @_;
$start //= 0;
return bless { value => $start }, $class;
}
sub increment {
my ($self) = @_;
$self->{value}++;
return $self->{value};
}
sub value {
my ($self) = @_;
return $self->{value};
}
package main;
my $counter = Counter->new(4);
print $counter->increment, "\n";
print $counter->value, "\n";
print ref($counter), "\n";
PERL
$ perl "$tmp_perl_object"
5
5
Counter
The constructor receives the class name, Counter, as its first argument. It blesses an anonymous hash into that class and returns the resulting object. The hash is the object's storage, so value is ordinary data inside the package's chosen representation.
In $counter->increment, the arrow calls a method and passes $counter as the first argument. That is why the method reads its object from $_[0], here unpacked as $self. The arrow is also used for dereferencing, but those are separate operations that happen to share syntax.
3. Verify what was blessed
A variable is not blessed. The referent, such as the hash behind a scalar reference, is associated with a package. Use Scalar::Util::blessed when you need to distinguish a blessed object from an ordinary reference:
$ perl -MScalar::Util=blessed -e '
my $object = bless {}, "Counter";
print blessed($object) // "not blessed", "\n";
'
Counter
If two variables refer to the same hash, blessing through either variable affects the same referent. If one variable is later assigned a string, that variable no longer contains the object. This is a common debugging trap when code reuses a scalar for unrelated values.
4. Add a parent class
Inheritance is method inheritance. The child class can reuse methods from a parent, but Perl does not automatically inherit attributes or construct them for you. Add a parent package to the temporary script, before the main package:
package NamedCounter;
use parent -norequire, 'Counter';
sub label {
my ($self, $name) = @_;
return "$name: " . $self->value;
}
package main;
my $named = NamedCounter->new(9);
print $named->label('items'), "\n";
print $named->increment, "\n";
Append that block before the final end of the original script, then run it again. The -norequire option is appropriate here because Counter is declared in the same file. In a real module split across files, use use parent 'Counter'; so Perl also loads the parent module.
$ perl "$tmp_perl_object"
5
5
Counter
items: 9
10
NamedCounter does not define new, increment or value. Perl searches the child package and then its parent classes until it finds the requested method. The object remains a NamedCounter object, even when the method body comes from Counter.
5. Override safely with SUPER
A child can replace a parent method and still call the parent's implementation through the SUPER pseudo-class:
sub increment {
my ($self) = @_;
my $new_value = $self->SUPER::increment;
return "updated to $new_value";
}
Put this subroutine inside NamedCounter and call $named->increment. It should print updated to 10 if the earlier label example has already incremented the object. SUPER is resolved from the package containing the method call, not guessed from the object's runtime class. Keep that rule in mind when moving methods between packages.
For multiple inheritance, Perl's default lookup is depth-first and left-to-right. The mro pragma can request C3 method resolution, but add it only when the inheritance graph needs a defined alternative. A missing method is an error; adding another parent is not a substitute for checking the package name and spelling.
6. Clean up and recover from mistakes
Remove the temporary script when you have finished checking it:
$ rm -- "$tmp_perl_object"
This removes only the file created by mktemp. If you used a different path, check it with printf '%s\n' "$tmp_perl_object" before deleting anything. The script does not alter Perl's installation or any persistent configuration.
If the interpreter reports that a method cannot be found, first check the package declaration, the spelling of the method, and whether the parent was loaded. If a method unexpectedly changes state, inspect the hash keys and remember that Perl does not enforce encapsulation: outside code can reach a blessed hash unless the class deliberately uses another design.
Done means
perl -vreports the installed version you intended to test.- A constructor returns a blessed object and stores initial state.
- An arrow method call passes the object as its first argument.
blessedandrefconfirm the object's package association.- A child class reuses a parent method, with
SUPERavailable for an override. - The temporary script is removed, and no elevated command was needed.