Обьекты и модули
Модуль - это отдельный файл , который может включать один или более namespace.
Имя модуля должно совпадать с именем файла.
Для получения доступа к модулю используйте префикс use.
Для получения доступа к методу модуля используйте MyModule::MyMethod().
Можно также использовать более простой способ доступа к методам из другого модуля -
экспорт , при этом синтаксис обращения к такому методу очень прост .
Общий механизм экспорта :
use Exporter;
use vars qw(@ISA @EXPORT);
@ISA=qw(Exporter);
@EXPORT=("function1", "function2", "function3");
Exporter - это специальный встроенный модуль.
@EXPORT - специальная встроенная переменная.
Рассмотрим пример - модуль Calc :
# File: Calc.pm
#
package Calc;
use strict;
use Exporter;
use vars qw(@ISA @EXPORT);
@ISA=qw(Exporter);
@EXPORT = ("gcd");
# This function calculates the greatest common divisor of two integers
sub gcd
{
my $a = shift;
my $b = shift;
if ($b > $a)
{
($a, $b) = ($b , $a);
}
while ($a % $b > 0)
{
($a, $b) = ($b, $a % $b);
}
return $b;
}
1;
Пример использования функции gcd из этого модуля :
use strict;
use Calc;
my $a = 200;
my $b = 15;
print "gcd(\$a,\$b) == " , gcd($a,$b), "\n";
Также возможен импорт-экспорт глобальных переменных для нескольких модулей.
Такие переменные должны быть обьявлены с префиксом use vars qw($myvar1 @myvar2)
Пример использования :
package MyVar;
use strict;
# Declare a namespace-scoped variable named $myvar.
use vars qw($myvar);
sub print_myvar
{
print $myvar, "\n";
}
1;
Использование глобальной переменной myvar:
use strict;
use MyVar;
$MyVar::myvar = "Hello";
MyVar::print_myvar();
$MyVar::myvar = "World";
MyVar::print_myvar();
В модулях есть 2 специальных блока - BEGIN и END ,
которые срабатывают при загрузке и выгрузке модуля :
package MyLog;
BEGIN
{
open MYLOG, ">mylog.txt";
}
sub log
{
my $what = shift;
# Strip the string of newline characters
$what =~ s/\n//g;
# The MYLOG filehandle is already open by virtue of the BEGIN
# block.
print MYLOG $what, "\n";
}
END
{
close(MYLOG);
}
1;
В чем разница между namespace(package) и модулем ?
namespace - он же package - это контейнер для пространства имен и методов ,
например : MyPackage::MySubPack::my_func() , где один модуль ссылается на другой.
Модуль - это отделный файл , который может входить в несколько namespace.
Обьект в перле - это ссылка. Для использования метода обьекта нужно применять префикс
$object_ref->method_name(@args).
Обьявим класс Foo :
#
# Foo.pm
#
package Foo;
sub new
{
# Retrieve the package's string.
# It is not necessarily Foo, because this constructor may be
# called from a class that inherits Foo.
my $class = shift;
# $self is the the object. Let's initialize it to an empty hash
# reference.
my $self = {};
# Associate $self with the class $class. This is probably the most
# important step.
bless $self, $class;
# Now we can retrieve the other arguments passed to the
# construtor.
my $name = shift || "Fooish";
my $number = shift || 5;
# Put these arguments inside class members
$self->{'name'} = $name;
$self->{'number'} = $number;
# Return $self so the user can use it.
return $self;
}
sub get_name
{
# This step is necessary so it will be treated as a method
my $self = shift;
return $self->{'name'};
}
sub assign_name
{
my $self = shift;
# Notice that we can pass regular arguments from now on.
my $new_name = shift || "Fooish";
$self->{'name'} = $new_name;
return 0;
}
1;
Содадим обьект от этого класса :
use strict;
use Foo;
my $foo = Foo->new("MyFoo", 500);
print $foo->{'name'}, "\n";
print $foo->get_name(), "\n";
$foo->assign_name("Shlomi Fish");
print $foo->get_name(), "\n";
В перле возможен явный вызов перегруженной функции базового класса.
Для этого нужно применять префикс SUPER.
В следующем примере сделан явный вызов assign_name из базового класса ,
несмотря на то , что он перегружен :
package Bar2;
use strict;
use vars qw(@ISA);
use Foo;
@ISA=qw(Foo);
sub assign_name
{
my $self = shift;
my $name = shift;
# Call the method of the base class
my $ret = $self->SUPER::assign_name($name);
if (! $ret)
{
$self->{'num_times'}++;
}
return $ret;
}
sub get_num_times_assigned
{
my $self = shift;
return
(exists($self->{'num_times'}) ?
$self->{'num_times'} :
0
);
}
1;
Деструкторы в перле реализованы с помощью ключевого слова DESTROY.
Он вызывается при выгрузке модуля.
package Count;
use strict;
use vars qw(@ISA);
use Bar2;
@ISA=qw(Bar2);
sub DESTROY
{
my $self = shift;
print "My name was assigned " . $self->get_num_times_assigned() . " times.\n";
}
1;
В перле есть 2 специальных встроенных метода.
isa() - если в качестве параметра этой функции задать имя пакета ,
эта функция определит , является ли текущий обьект потомком от этого пакета.
can() - если в качестве аргумента задать имя метода ,
функция определит , может ли обьект выполнять данный метод.
|