Perl Object-Oriented Programming

There are two different implementations of object-oriented programming in Perl:

  • One is based on anonymous hash tables, where the essence of each object instance is a reference to an anonymous hash table. In this anonymous hash table, all instance attributes are stored.

  • The other is based on arrays. When defining a class, we create an array for each instance attribute, and the essence of each object instance is a reference to an index of a row in these arrays. In these arrays, all instance attributes are stored.


Object-Oriented Basic Concepts

Object-oriented programming has many basic concepts. Here we cover three: objects, classes, and methods.

  • ObjectAn object is a reference to a data item in a class.

  • ClassA class is a Perl package that contains the methods provided for the object.

  • MethodA method is a Perl subroutine whose first parameter is the class name.

Perl provides the bless() function, which is used to construct objects. By associating a reference with the class name via bless, returning this reference constructs an object.


Class Definition

A class is just a simple package.

You can use a package as a class and use the functions in the package as methods of the class.

Perl packages provide independent namespaces, so methods and variable names from different packages do not conflict.

Perl class files have the extension .pm.

Next, we create a Person class:

package Person;

The scope of a class's code extends to the last line of the script file, or to the next "package" keyword.


Creating and Using Objects

To create an instance (object) of a class, we need to define a constructor. Most programs use the class name as the constructor, but in Perl you can use any name.

You can use various Perl variables as Perl objects. In most cases, we use references to arrays or hashes.

Next, we create a constructor for the Person class, using a Perl hash reference.

When creating an object, you need to provide a constructor, which is a subroutine that returns a reference to the object.

The example is as follows:

Example

package Person; sub new { my $class = shift; my $self = { _firstName => shift, _lastName => shift, _ssn => shift, }; # Output user information print "Name:$self->{_firstName}\n"; print "Surname:$self->{_lastName}\n"; print "Number:$self->{_ssn}\n"; bless $self, $class; return $self; }

Next, we create an object:

$object = new Person( "小明", "王", 23234345);

Defining Methods

Perl class methods are just Perl subroutines, i.e., what are commonly called member functions.

In Perl OOP, method definition does not provide any special syntax, but it does require that the first parameter of a method be the object or the package it is referenced from.

Perl does not provide private variables, but we can manage object data through auxiliary methods.

Next, we define a method to get the name:

sub getFirstName {
    return $self->{_firstName};
}

It can also be written like this:

sub setFirstName {
    my ( $self, $firstName ) = @_;
    $self->{_firstName} = $firstName if defined($firstName);
    return $self->{_firstName};
}

Next, we modify the code in the Person.pm file as follows:

Example

#!/usr/bin/perl package Person; sub new { my $class = shift; my $self = { _firstName => shift, _lastName => shift, _ssn => shift, }; # Output user information print "Name:$self->{_firstName}\n"; print "Surname:$self->{_lastName}\n"; print "Number:$self->{_ssn}\n"; bless $self, $class; return $self; } sub setFirstName { my ( $self, $firstName ) = @_; $self->{_firstName} = $firstName if defined($firstName); return $self->{_firstName}; } sub getFirstName { my( $self ) = @_; return $self->{_firstName}; } 1;

The employee.pl script code is as follows:

Example

#!/usr/bin/perl use Person; $object = new Person( "Xiaoming", "Wang", 23234345); # Get name $firstName = $object->getFirstName(); print "Name before setting is :$firstName\n"; # Use helper function to set name $object->setFirstName( "Xiaoqiang" ); # Get name via helper function $firstName = $object->getFirstName(); print "Name after setting is :$firstName\n";

After executing the above program, the output is:

$ perl employee.pl
名字:小明
姓氏:王
编号:23234345
设置前姓名为 : 小明
设置后姓名为 : 小强

Inheritance

In Perl, class methods are inherited through the @ISA array, which contains the names of other packages (classes). Variable inheritance must be explicitly set.

Multiple inheritance is when this @ISA array contains multiple class (package) names.

Through @ISA, only methods can be inherited; data cannot be inherited.

Next, we create an Employee class that inherits from the Person class.

The Employee.pm file code is as follows:

Example

#!/usr/bin/perl package Employee; use Person; use strict; our @ISA = qw(Person); # Inherit from Person

Now the Employee class contains all methods and attributes of the Person class. We enter the following code in the main.pl file and execute it:

Example

#!/usr/bin/perl use Employee; $object = new Employee( "Xiaoming", "Wang", 23234345); # Get name $firstName = $object->getFirstName(); print "Name before setting is :$firstName\n"; # Use helper function to set name $object->setFirstName( "Xiaoqiang" ); # Get name via helper function $firstName = $object->getFirstName(); print "Name after setting is :$firstName\n";

After executing the above program, the output is:

$ perl main.pl
名字:小明
姓氏:王
编号:23234345
设置前姓名为 : 小明
设置后姓名为 : 小强

Method Overriding

In the example above, the Employee class inherits from the Person class. However, if the methods of the Person class cannot meet the requirements, they need to be overridden.

Next, we add some new methods to the Employee class and override methods of the Person class:

Example

#!/usr/bin/perl package Employee; use Person; use strict; our @ISA = qw(Person); # Inherit from Person # Override constructor sub new { my ($class) = @_; # Call parent class constructor my $self = $class->SUPER::new( $_[1], $_[2], $_[3] ); # Add more attributes $self->{_id} = undef; $self->{_title} = undef; bless $self, $class; return $self; } # Override method sub getFirstName { my( $self ) = @_; # This is a subclass function print "This is a subclass function\n"; return $self->{_firstName}; } # Add method sub setLastName{ my ( $self, $lastName ) = @_; $self->{_lastName} = $lastName if defined($lastName); return $self->{_lastName}; } sub getLastName { my( $self ) = @_; return $self->{_lastName}; } 1;

We enter the following code in the main.pl file and execute it:

Example

#!/usr/bin/perl use Employee; $object = new Employee( "Xiaoming", "Wang", 23234345); # Get name, using modified constructor $firstName = $object->getFirstName(); print "Name before setting is :$firstName\n"; # Use helper function to set name $object->setFirstName( "Xiaoqiang" ); # Get name via helper function $firstName = $object->getFirstName(); print "Name after setting is :$firstName\n";

After executing the above program, the output is:

$ perl main.pl
名字:小明
姓氏:王
编号:23234345
这是子类函数
设置前姓名为 : 小明
这是子类函数
设置后姓名为 : 小强

Autoload

If the requested method cannot be found in the current class, all base classes of the current class, or the UNIVERSAL class, Perl then looks for a method named AUTOLOAD(). If AUTOLOAD is found, it is called, and the global variable $AUTOLOAD is set to the fully qualified name of the missing method.

If that still fails, Perl declares an error and fails.

If you don't want to inherit AUTOLOAD from the base class, it's simple: just one line:

sub AUTOLOAD;

Destructors and Garbage Collection

When the last reference to an object is released, the object is automatically destroyed.

If you want to do something during destruction, you can define a method named "DESTROY" in the class. It is automatically called at an appropriate time and performs additional cleanup actions as you define.

package MyClass;
...
sub DESTROY
{
    print "MyClass::DESTROY called\n";
}

Perl passes the object reference as the sole parameter to DESTROY. Note that this reference is read-only, meaning you cannot modify it by accessing $_

If you re-bless the object reference before the destructor returns, Perl will then call the DESTROY method of the object you re-blessed after the destructor returns. This gives you the opportunity to call the destructor of the base class or another class you specify. It should be noted that DESTROY can also be called manually, but it is usually unnecessary.

After the current object is released, other objects contained in the current object are automatically released.


Perl Object-Oriented Example

We can further understand the application of Perl OOP through the following example:

Example

#!/usr/bin/perl # The following is a simple class implementation package MyClass; sub new { print "MyClass::new called\n"; my $type = shift; # Package name my $self = {}; # Reference an empty hash return bless $self, $type; } sub DESTROY { print "MyClass::DESTROY called\n"; } sub MyMethod { print "MyClass::MyMethod called!\n"; } # Inheritance implementation package MySubClass; @ISA = qw( MyClass ); sub new { print "MySubClass::new called\n"; my $type = shift; # Package name my $self = MyClass->new; # Reference an empty hash return bless $self, $type; } sub DESTROY { print "MySubClass::DESTROY called\n"; } sub MyMethod { my $self = shift; $self->SUPER::MyMethod(); print " MySubClass::MyMethod called!\n"; } # Main program calling the above classes package main; print "Calling MyClass method\n"; $myObject = MyClass->new(); $myObject->MyMethod(); print "Calling MySubClass method\n"; $myObject2 = MySubClass->new(); $myObject2->MyMethod(); print "Creating a scoped object\n"; { my $myObject2 = MyClass->new(); } # Automatically call destructor print "Create object\n"; $myObject3 = MyClass->new(); undef $myObject3; print "Script execution ended...\n"; # Automatic Destructor Execution

Executing the above program, the output is:

调用 MyClass 方法
MyClass::new called
MyClass::MyMethod called!
调用 MySubClass 方法
MySubClass::new called
MyClass::new called
MyClass::MyMethod called!
   MySubClass::MyMethod called!
创建一个作用域对象
MyClass::new called
MyClass::DESTROY called
创建对象
MyClass::new called
MyClass::DESTROY called
脚本执行结束...
MyClass::DESTROY called
MySubClass::DESTROY called
Other Extensions