本文概述
Perl为我们提供了一些构建面向对象系统的工具。 Perl面向对象的概念基于引用, 匿名数组和哈希。
Perl基本对象
一个对象只是一个数据结构, 它知道它所属的类名。它作为参考存储在标量变量中。相同的标量变量可以保存不同类中的不同对象, 因为它仅保存对对象的引用。
一个类就是一个包。它包含对对象进行操作(创建和操作)的方法。
方法是一个子例程, 该例程将对象引用或程序包名称作为第一个参数。
Perl类声明
要创建一个类, 我们需要在Perl中创建一个包。程序包包含可以重用的变量和子例程。
由于每个类都是一个包, 因此它具有自己的名称空间, 该名称空间由符号名称组成。类是使用package关键字创建的名称空间。通常在与类同名的模块中实现。例如, My ::文件将在File.pm文件中实现, 位置将是目录My, 其内容如下。
package My::File;
use strict;
use warnings;
1;
此处的末尾1表示文件已成功加载。
包的范围扩展到文件末尾, 或者直到遇到另一个包关键字。
Perl构造函数
代码需要一个功能完整的类的构造函数。
通常, 构造函数是作为新方法实现的。
sub new {
my ($class, %args) = @_;
return bless \%args, $class;
}
Perl实例/对象
实例或对象主要是对哈希的祝福引用。祝福某事意味着我们祝福该变量所指的事物。
use Scalar::Util 'blessed';
my $Ana = {};
my $Christian = $Ana;
bless $Ana, 'Happiness';
print blessed( $Christian ) // 'not blessed'; # Class
print "\n";
$Christian = "some other value";
print blessed( $Christian ) // 'not blessed'; # not blessed
print "\n";
输出
Class
not blessed
在上面的程序中, 当我们对变量调用”保佑”时, 我们保佑变量所引用的数据结构。参考没有得到祝福。因此, 当我们第二次调用blessed($ Christian)时, 它将返回false。因为$ Christian没有存储对对象的引用。
Perl析构函数
Perl析构函数用于清除不再需要分配给对象的内存。当对象超出范围时, 它将在Perl中自动完成。因此, 它通常不在Perl中实现。
为了实现析构函数, 这里有一个称为DESTROY的函数。在Perl销毁对象并回收内存之前调用它。
package MyExample;
sub DESTROY {
my ($self) = @_;
print "MyExample::DESTROY called\n";
}
Perl定义方法
在Perl中没有特殊的语法来定义方法。它只是一个普通的子例程, 用’sub’关键字声明。
方法将对象或类名作为其第一个参数。
要调用方法, 请使用->运算符。
要将方法作为对象调用, 使用以下语法:
$object -> method
左边有对象名, 右边有方法名。
调用方法时, 左侧对象作为第一个参数传递到右侧。
例:
在此示例中, 我们将设置一个帮助方法和一个帮助函数来设置学生的姓名和等级。
步骤1在hw.pl文件中, 定义一个帮助方法studentName以获取学生的姓名。
定义一个辅助函数studentRank以获取学生的排名。
sub studentName {
return $self->{_name};
}
sub studentRank {
my ( $self, $name ) = @_;
$self->{_name} = $name if defined($name);
return $self->{_name};
}
步骤2在student.pm文件中, 编写Student package和helper函数。
#!/usr/bin/perl
package Student;
sub new
{
my $class = shift;
my $self = {
_name => shift, _rank => shift, };
# Print all the values just for clarification.
print "Student's name is $self->{_name}\n";
print "Student's rank is $self->{_rank}\n";
bless $self, $class;
return $self;
}
sub studentRank {
my ( $self, $name ) = @_;
$self->{_name} = $name if defined($name);
return $self->{_name};
}
sub studentName {
my( $self ) = @_;
return $self->{_name};
}
1;
步骤3在person.pl文件中, 我们将使用Student对象获取输出。
#!/usr/bin/perl
use Student;
$object = new Student( "Ana", "9th");
# name which is set using constructor.
$name = $object->studentName();
print "Name set using constructor is : $name\n";
# name set using helper function.
$object->studentRank( "Anastasia" );
# getting name set by helper function.
$name = $object->studentName();
print "Name set using helper is : $name\n";
输出
Student's name is Ana
Student's rank is 9th
Name set using constructor is : Ana
Name set using helper is : Anastasia
Perl继承
继承意味着子类将继承父类的属性和方法。因此, 要重用代码, 你可以简单地继承它。在Perl中, @ ISA数组定义继承。
使用继承时, 应考虑以下几点:
- 它将搜索给定方法的对象类, 即;变量。
- 它搜索在对象类的@ISA数组中定义的类。
- 如果在上述步骤中未找到任何方法, 它将使用AUTOLOAD子例程。
- 如果仍然找不到方法, 它将使用UNIVERSAL类进行搜索, 该类是标准Perl库的一部分。
- 如果仍然找不到, 则会发生运行时异常。
也可以使用父指令声明继承, 该指令取代了较早的基本指令。
例:
我们的脚本加载一个模块, 调用其构造函数, 然后调用两个方法。
使用以下脚本创建hw.pl文件。在这里, 模块本身使用父指令声明其继承。
#!/usr/bin/perl
use strict;
use warnings;
use Module1;
my $myObj = Module1->new;
$myObj->setHello;
$myObj->setBye;
输出
This is Hello message from Module1
This is Bye message from Module2
使用以下脚本创建Module1.pm文件。它从继承构造函数和其他方法的位置声明模块。
package Module1;
use strict;
use warnings;
use parent 'Module2';
sub setHello {
print "This is Hello message from Module1\n";
}
1;
使用以下脚本创建Module2.pm文件。
package Module2;
use strict;
use warnings;
sub new {
my ($class) = @_;
return bless {}, $class;
}
sub setBye {
my ($self) = @_;
print "This is Bye message from Module2\n";
return;
}
1;
从Module1调用新方法时, Perl不会在Module1中找到它。它将在继承链中的下一个模块Module2中查找它。因此, 将从Module2中调用新方法。
Perl多态性
多态性意味着基类中定义的方法将覆盖父类中定义的方法。
它附加了现有类的功能, 而无需重新编程整个类。
例:
package A;
sub A1 {
print("Inside A::A1\n");
}
package B;
@ISA = (A);
sub A1 {
print("Inside B::B1\n");
}
package main;
B->A1();
输出
Inside B::B1
在类B中定义的子A1覆盖了从类A继承的子类。