У меня есть файл perl mason, и одна из строк выглядит так:
$result = PI::Membership::Service->cancel(name => $name)
Что именно это значит? Он вызывает другой модуль? Это объектно-ориентированный Perl-код?
Спасибо
У меня есть файл perl mason, и одна из строк выглядит так:
$result = PI::Membership::Service->cancel(name => $name)
Что именно это значит? Он вызывает другой модуль? Это объектно-ориентированный Perl-код?
Спасибо
Он вызывает (вызывает) подпрограмму PI::Membership::Service::cancel
с тремя аргументами.
"PI::Membership::Service"
"name"
$name
Учитывая обычные соглашения об именах, это вызывает подпрограмму с именем cancel
в пакете PI::Membership::Service
, определенную в файле с именем PI/Membership/Service.pm
где-то по пути @INC
(однако существует много ненормальных соглашений об именах, поэтому нет гарантии, что вы найдете такой файл) . И если пакет (класс) PI::Membership::Service
наследуется от одного или нескольких других пакетов, подпрограмма cancel
фактически может быть определена в одном из этих пакетов.
Подробнее см. perlobj
.
use
или require
.
- person tjd; 08.07.2013
PI::Membership::Service
не наследует метод cancel
. Он может быть определен в родительском классе.
- person friedo; 08.07.2013
Если $result
не является объектом Pi::Membership::Service
, это не совсем объектно-ориентированный вызов, потому что он не создает объект и не манипулирует им. Объектно-ориентированный вызов будет выглядеть так:
my $obj = Foo::Bar->new; #Creating an object of class `Foo::Bar`
$obj->Baz #Calling method "Baz" on object "$obj";
Похоже, что это вызов объектного стиля для доступа к подпрограмме, которая находится в другом пакете и не была экспортирована.
Чтобы понять, что происходит на самом деле, вы должны знать о пространствах имен. Perl использует пространства имен. В большинстве случаев вы можете не знать об этом, потому что используете пространство имен по умолчанию main
. Пространства имен необходимы, потому что вы можете столкнуться (особенно в версиях Perl до 4.x) с конфликтами имен функций и переменных. Вот программа, которую я написал в старом стиле Perl 3.x:
require "fribulate.pl";
$value = 4.5;
$new_value = fribulate($value);
print "Fribulated Value = $new_value Original value = $value\n";
А вот моя программа fribulate.pl
:
sub fribulate {
my $param = shift;
$value = $param * 2;
return $value * 6;
}
1;
Когда я запускаю свою программу, я получаю:
Fribulated Value = 54. Original Value = 9
Ждать? Разве изначально не 4,5? Программа fribulate.pl
повлияла на мой $value
, потому что она также использует переменную с именем $value
. Чтобы обойти это, Perl создал команду package
, которая создает новое пространство имен:
package Fribulate;
sub fribulate {
my $param = shift;
$value = $param * 2;
return $value * 3.1416;
}
1;
Теперь программа fribulate.pl
находится не в пространстве имен main
, а в пространстве имен Fribulate
. Таким образом, переменная $value
, используемая в fribulate.pl
, отличается от моей переменной $value
.
Однако я могу получить доступ к переменной в другом пространстве имен, если я добавлю к ней пространство имен:
require "fribulate.pl";
$value = 4.5;
$new_value = fribulate($value);
print "Fribulated Value = $new_value Original value = $value\n";
# Printing the value of $value from frimbulate.pl:
print "And in fribulate.pl, it's using $Fribulate::value\n";
Вы бы увидели это, если бы использовали Файл:Найти. Чтобы получить доступ к полному имени файла, вы используете $File::Find::name
. Чтобы получить доступ к каталогу файла, вы используете $File::Find::dir
. Пространство имен File::Find
добавляется к переменным $dir
и $name
в File::Find
.
Проблема с пространствами имен заключается в том, что все теперь находится в новом пространстве имен, включая мою функцию frimbulate
в frimbulate.pl
. Таким образом, моя исходная программа также должна добавлять пространство имен перед функцией, чтобы работать:
require "fribulate.pl";
$value = 4.5;
$new_value = Frimbulate::fribulate($value);
print "Fribulated Value = $new_value Original value = $value\n";
Чтобы обойти эту проблему, вы проделали небольшую причудливую работу в программе frimbulate.pl
:
Package Frimbulate;
require Exporter;
@EXPORT = qw(frimbulate);
sub fribulate {
my $param = shift;
$value = $param * 2;
return $value * 3.1416;
}
1;
Пакет Exporter
посыпает волшебной пылью1 функции в @EXPORT
и делает их доступными в пространстве имен main
— пространстве имен по умолчанию, в котором находятся все ваши вещи. Таким образом, такие модули, как File::Copy и File::Basename используйте Exporter
, чтобы разрешить вам доступ к соответствующим подпрограммам copy
и basename
без добавления имени пакета перед ними.
Теперь это считается плохим стилем, потому что вы можете без предупреждения перезаписать другие подпрограммы с тем же именем. В новом стиле написания модулей вы больше не экспортируете автоматически все свои функции в массив @EXPORT
. Вы заметите это в File::Path, который не экспортирует свои функции автоматически в пространство имен main
без нашего явного запроса. Вместо этого вы помещаете их в @EXPORT_OK
, что требует, чтобы пользователи просили их добавить в пространство имен:
Package Frimbulate;
require Exporter;
@EXPORT_OK = qw(frimbulate); #You have to request the frimbulate subroutine
sub fribulate {
my $param = shift;
$value = $param * 2;
return $value * 3.1416;
}
1;
# Now I have to ask that the frimbulate subroutine be import into my main namespace
require "fribulate.pl" qw(frimbulate);
$value = 4.5;
$new_value = fribulate($value);
print "Fribulated Value = $new_value Original value = $value\n";
Теперь у вас должно быть достаточно информации, чтобы прочитать документацию по модулю Perl и, вполне возможно, понять, что происходит. Документация Perlmod охватывает пространства имен, таблицу символов и даже немного об области видимости переменных. Он содержит много информации и может быть немного пугающим без базовой информации.
1 При использовании модуля Exporter ни одна пикси не пострадала. Если вы посмотрите на Exporter.pm
, который вы можете найти с помощью команды perldoc -l Exporter
, вы увидите, что он напрямую манипулирует таблицей символов.