Скажем, у меня есть файл модуля жемчуга, и я хочу включать и использовать его динамично во времени выполнения. Упомянутый модуль включает класс, которого я должен инстанцировать, не зная его имя до времени выполнения.
Например,
#inside module.pm
package module;
sub new {
#setup object
}
#inside main.pl
#get module.pm as argument
my $module_var = #load reference to module using text argument?
my $module_instance = $module_var->new();
Это можно сделать без eval следующим образом:
my $module_name = 'Some::Module';
(my $require_name = $module_name . ".pm") =~ s{::}{/}g;
require $require_name;
my $obj = $module_name->new();
Если вам нужно сделать это много раз, просто заключите этот код в подпрограмму:
sub load_module {
for (@_) {
(my $file = "$_.pm") =~ s{::}{/}g;
require $file;
}
}
load_module 'Some::Module', 'Another::Module';
my $module_var = 'module';
eval "use $module_var; 1" or die $@;
my $module_instance = $module_var->new();
Обратите внимание, что eval
является возможной дырой в безопасности. Если $ module_var
содержит код, он будет выполнен. Один из способов обойти это - использовать Class :: MOP . Замените строку eval
на:
use Class::MOP;
Class::MOP::load_class($module_var);
Если вы не хотите требовать Class :: MOP, вы можете скопировать из него функцию _is_valid_class_name
в свой код и просто убедитесь, что что $ module_var
содержит допустимый класс до того, как вы eval
его. (Обратите внимание, что если вы используете Moose , вы уже используете Class :: MOP за кадром.)
Вы можете сделать это с помощью eval
.
my $module = "Foo";
eval "use $module;1" or die($@); # Couldn't load module