在perl中按需加载所需的包

Nem*_*emo 7 perl moose

重新提出的问题 - 抱歉,这有点长.

例如,有一个简单的包

package My;
use Moose;
use namespace::sweep;
sub cmd1 {1}
sub smd2 {2}
__PACKAGE__->meta->make_immutable;
1;
Run Code Online (Sandbox Code Playgroud)

我希望允许My其他方法扩展其他方法,例如

package My::Cmd3;
use Moose;
extends 'My';
sub cmd3 {3}
1;
Run Code Online (Sandbox Code Playgroud)

这允许使用"基础" MyMy::Cmd3下一个方法:

use My::Cmd3;
my $obj = My::Cmd3->new();
say $obj->cmd1(); #from the base My
say $obj->cmd3(); #from the My::Cmd3;
Run Code Online (Sandbox Code Playgroud)

但这不是我想要的.我不想use My::Cmd3;,(这里会有更多扩展包),我想要use My;.

使用角色是NICER,如:

package My;
use Moose;
with 'My::Cmd3';
sub cmd1 {1}
sub cmd2 {2}
__PACKAGE__->meta->make_immutable;
1;

package My::Cmd3;
use Moose::Role;
use namespace::autoclean;       
sub cmd3 {3};
no Moose::Role;
1;
Run Code Online (Sandbox Code Playgroud)

这让我:

use My;
my $obj = My->new();
say $obj->cmd1();
say $obj->cmd3(); #from the role-package
Run Code Online (Sandbox Code Playgroud)

但是当有人制作My::Cmd4遗嘱时需要更改基础My包添加with My::Cmd4.(

我正在寻找一种方法,如何实现下一步:

use My;

#and load all needed packages on demand with the interface like the next
my $obj = My->new( commands => [qw(Cmd3 Cmd4)] );
#what should load the methods from the "base" My and from the wanted extensions too

say $obj->cmd1(); # from the base My package
say $obj->cmd3(); # from the "extension" package My::Cmd3
say $obj->cmd4(); # from the My::Cmd4
Run Code Online (Sandbox Code Playgroud)

所以,我现在拥有的:

package My;
use Moose;
has 'commands' => (
    is => 'rw',
    isa => 'ArrayRef[Str]|Undef', #??
    default => sub { undef },
);

# WHAT HERE?
# need something here, what loads the packages My::Names... based on the supplied "commands"
# probably the BUILD { ... } ???

sub cmd1 {1}
sub smd2 {2}
__PACKAGE__->meta->make_immutable;
1;
Run Code Online (Sandbox Code Playgroud)

设计正确的对象层次结构是我永恒的问题..;(

我绝对肯定,这不应该是一个大问题,只需要一些我应该学习的指针; 因此很高兴知道一些CPAN模块,使用这种技术的...

所以问题:

  • 我需要代替上面的"什么在这里?"
  • "扩展"包应该是角色吗?(可能它是最好的,但要求肯定)
  • 我是否应该将"基本"命令从"移动"移动到" My例如" My::Base并按需加载按需My::Something或是否应保留在My?为什么?
  • 其他一些建议?
  • 为了得到一个方法列表(和加载的包),我可以使用Moose
my $obj = My->new(....);
my @methods = $obj->meta->get_all_methods();
Run Code Online (Sandbox Code Playgroud)

这只是Moose,我不能使用更小的东西Moo,对吗?

Ps:对于极长的问题再次抱歉.

Mig*_*Prz 2

第一:继承

使用 Moo 或 Moose 是一项超级简单的任务:

package My::Sub3;
use Moo;
extends 'My';

sub cmd3 {3}
1;
Run Code Online (Sandbox Code Playgroud)

第二:动态对象构建。定义构建函数并在运行时加载正确的模块。有几种方法可以做到这一点,我喜欢Module::Load CPAN 模块:

use Module::Load;

sub my_factory_builder {
   my $class_name = shift;
   load $class_name;
   return $class_name->new(@_);
}
Run Code Online (Sandbox Code Playgroud)

然后,在您的代码中:

my @new_params = ();
my $object = my_factory_builder('My::Sub3', @new_params);
Run Code Online (Sandbox Code Playgroud)