Perl object-oriented


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

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

  • The second is based on the array method. When defining a class, we will create an array for each instance attribute, and the essence of each object instance is a pointer to these arrays. A reference to a row index. In these arrays, all instance properties are stored.


Basic concepts of object-oriented

There are many basic concepts of object-oriented, here we accept three: objects, classes and methods.

  • Object: An object is a reference to a data item in a class. .

  • Class: A class is a Perl package that contains classes that provide object methods.

  • Method: The method is a Perl subroutine, and the class name is its first parameter.

Perl provides the bless() function. bless is used to construct objects. Bless associates a reference with the class name and returns the reference to construct an object.


Definition of class

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 in different packages will not conflict.

The file suffix of Perl class is .pm.

Next we create a Person class:

package Person;

The code range of the class reaches the last line of the script file, or before the next package keyword.


Create and use objects

To create an instance (object) of a class we need to define a constructor. Most programs use the class name as the constructor. Any name can be used in Perl .

You can use various Perl variables as Perl objects. Most of the time we will use reference arrays or hashes.

Next we create a constructor for the Person class, using Perl’s 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:

package Person;
sub new
{
    my $class = shift;
    my $self = {
        _firstName => shift,
        _lastName  => shift,
        _ssn       => shift,
    };
    # 输出用户信息
    print "名字:$self->{_firstName}\n";
    print "姓氏:$self->{_lastName}\n";
    print "编号:$self->{_ssn}\n";
    bless $self, $class;
    return $self;
}

Next we create an object:

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

Define the method

The method of the Perl class is just a Perl child It's just a program, also known as a member function.

Perl's method definition in object-oriented Perl does not provide any special syntax, but stipulates that the first parameter of the method is an object or its referenced package.

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 of the Person.pm file, as shown below :

#!/usr/bin/perl 

package Person;

sub new
{
    my $class = shift;
    my $self = {
        _firstName => shift,
        _lastName  => shift,
        _ssn       => shift,
    };
    # 输出用户信息
    print "名字:$self->{_firstName}\n";
    print "姓氏:$self->{_lastName}\n";
    print "编号:$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;

employee.pl The script code is as follows:

#!/usr/bin/perl

use Person;

$object = new Person( "小明", "王", 23234345);
# 获取姓名
$firstName = $object->getFirstName();

print "设置前姓名为 : $firstName\n";

# 使用辅助函数设置姓名
$object->setFirstName( "小强" );

# 通过辅助函数获取姓名
$firstName = $object->getFirstName();
print "设置后姓名为 : $firstName\n";

After executing the above program, the output result is:

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

Inheritance

Perl class methods are inherited through the @ISA array. This array contains the names of other packages (classes). The inheritance of variables must be explicitly set.

Multiple inheritance means that the @ISA array contains multiple class (package) names.

Only methods can be inherited through @ISA, but data cannot be inherited.

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

The Employee.pm file code is as follows:

#!/usr/bin/perl

package Employee;
use Person;
use strict;
our @ISA = qw(Person);    # 从 Person 继承

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

#!/usr/bin/perl

use Employee;

$object = new Employee( "小明", "王", 23234345);
# 获取姓名
$firstName = $object->getFirstName();

print "设置前姓名为 : $firstName\n";

# 使用辅助函数设置姓名
$object->setFirstName( "小强" );

# 通过辅助函数获取姓名
$firstName = $object->getFirstName();
print "设置后姓名为 : $firstName\n";

After executing the above program, the output result is:

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

Method rewriting

In the above example, the Employee class inherits the Person class, but if the Person class If the method cannot meet the needs, the method needs to be rewritten.

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

#!/usr/bin/perl

package Employee;
use Person;
use strict;
our @ISA = qw(Person);    # 从 Person 继承

# 重写构造函数
sub new {
    my ($class) = @_;

    # 调用父类的构造函数
    my $self = $class->SUPER::new( $_[1], $_[2], $_[3] );
    # 添加更多属性
    $self->{_id}   = undef;
    $self->{_title} = undef;
    bless $self, $class;
    return $self;
}

# 重写方法
sub getFirstName {
    my( $self ) = @_;
    # 这是子类函数
    print "这是子类函数\n";
    return $self->{_firstName};
}

# 添加方法
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:

#!/usr/bin/perl

use Employee;

$object = new Employee( "小明", "王", 23234345);
# 获取姓名,使用修改后的构造函数
$firstName = $object->getFirstName();

print "设置前姓名为 : $firstName\n";

# 使用辅助函数设置姓名
$object->setFirstName( "小强" );

# 通过辅助函数获取姓名
$firstName = $object->getFirstName();
print "设置后姓名为 : $firstName\n";

After executing the above program, the output result is:

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

Loaded by default

If it is in the current class, all base classes of the current class, and the UNIVERSAL class I can't find a way to request it. At this time, a method named AUTOLOAD() is looked for again. If AUTOLOAD is found, then Call, and set the global variable $AUTOLOAD to the fully qualified name of the missing method.

If that doesn't work, Perl will fail with an error.

If you don’t want to inherit AUTOLOAD of the base class, it’s very simple, just one sentence:

sub AUTOLOAD;

Destructor and garbage collection

When the last reference of the object When released, the object is automatically destroyed.

If you want to do something during destruction, then you can define a method named "DESTROY" in the class. It will be automatically called at the right time and perform additional cleanup actions as you wish.

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

Perl treats object references as The only argument passed is DESTROY. Note that this reference is read-only, which means you cannot modify it by accessing $_[0]. (Translator's Note: See perlsub) But the object itself (such as "${$_[0]" Or "@{$_[0]}" and "%{$_[0]}" etc.) are still writable.

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 other classes that you specify. It should be noted that DESTROY can also be called manually, but it is usually not necessary to do so.

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


Perl object-oriented example

We can further understand the object-oriented application of Perl through the following examples:

#!/usr/bin/perl

# 下面是简单的类实现
package MyClass;

sub new
{
   print "MyClass::new called\n";
   my $type = shift;            # 包名
   my $self = {};               # 引用空哈希
   return bless $self, $type;   
}

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

sub MyMethod
{
   print "MyClass::MyMethod called!\n";
}


# 继承实现
package MySubClass;

@ISA = qw( MyClass );

sub new
{
   print "MySubClass::new called\n";
   my $type = shift;            # 包名
   my $self = MyClass->new;     # 引用空哈希
   return bless $self, $type;  
}

sub DESTROY
{
   print "MySubClass::DESTROY called\n";
}

sub MyMethod
{
   my $self = shift;
   $self->SUPER::MyMethod();
   print "   MySubClass::MyMethod called!\n";
}

# 调用以上类的主程序
package main;

print "调用 MyClass 方法\n";

$myObject = MyClass->new();
$myObject->MyMethod();

print "调用 MySubClass 方法\n";

$myObject2 = MySubClass->new();
$myObject2->MyMethod();

print "创建一个作用域对象\n";
{
  my $myObject2 = MyClass->new();
}
# 自动调用析构函数

print "创建对象\n";
$myObject3 = MyClass->new();
undef $myObject3;

print "脚本执行结束...\n";
# 自动执行析构函数

Execute the above program, the output result 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