📅  最后修改于: 2021-01-07 08:40:08             🧑  作者: Mango
Perl为我们提供了一些构建面向对象系统的工具。 Perl面向对象的概念基于引用,匿名数组和哈希。
一个对象只是一个数据结构,它知道它所属的类名。它作为参考存储在标量变量中。相同的标量变量可以仅包含对对象的引用,因此可以将不同的对象包含在不同的类中。
一个类就是一个包。它包含对对象进行操作(创建和操作)的方法。
方法是一个子例程,该例程将对象引用或程序包名称作为第一个参数。
要创建一个类,我们需要在Perl中创建一个包。程序包包含可以重用的变量和子例程。
因为每个类都是一个包,所以它有自己的名称空间,该名称空间由符号名称组成。类是使用package关键字创建的名称空间。通常在与类同名的模块中实现。例如, My ::文件将在File.pm文件中实现,位置将是目录My ,其内容如下。
package My::File;
use strict;
use warnings;
1;
此处的末尾1表示文件已成功加载。
包的范围扩展到文件末尾,或者直到遇到另一个包关键字。
代码需要一个功能完整的类的构造函数。
通常,构造函数是作为新方法实现的。
sub new {
my ($class, %args) = @_;
return bless \%args, $class;
}
实例或对象主要是对哈希的祝福引用。祝福某事意味着我们祝福该变量所指的事物。
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中实现。
为了实现析构函数,这里有一个称为DESTROY的函数。在Perl销毁对象并回收内存之前调用它。
package MyExample;
sub DESTROY {
my ($self) = @_;
print "MyExample::DESTROY called\n";
}
在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中,@ ISA数组定义继承。
使用继承时,应考虑以下几点:
也可以使用父指令声明继承,该指令取代了较早的基本指令。
例:
我们的脚本加载一个模块,调用其构造函数,然后调用两个方法。
使用以下脚本创建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调用新方法。
多态性意味着基类中定义的方法将覆盖父类中定义的方法。
它附加了现有类的功能,而无需重新编程整个类。
例:
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继承的子类。