你如何"懒惰加载"包用作代表?

qod*_*nja 2 oop perl delegates moose

有没有办法可以动态地包含基于任何委托使用的包而不必包括所有各种代表?

我找到了关于如何使用委托的这个例子,但它掩盖了我试图理解的细节.这是写的方式,它基本上都是一个文件......

package Compare;
use Moose::Role;
requires 'compare';


package SpaceshipCompare;
use Moose;
with 'Compare';  

sub compare { my ($a, $b) = @_; return $a <=> $b }

package Sort;
use Moose;

has 'comparer' => (
    is       => 'ro',
    does     => 'Compare',
    handles  => 'Compare',
    required => 1,
);

sub my_sort {
    my ($self, @list) = @_;
    return sort { $self->compare($a, $b) } @list;
}
Run Code Online (Sandbox Code Playgroud)

用法:

my $sorter = Sort->new( comparer => SpaceshipCompare->new );
my @sorted = $sorter->my_sort("1one", "0", "43");
Run Code Online (Sandbox Code Playgroud)

在我的委托实现中,我正在使用基于传递给构造函数的参数的不同资源.

  sub BUILD{
    my($this,$args) = @_;

        if($args->{cachedDataSource} eq 'local'){

            $this->setDataStore( Cache::LocalCache->new() ); 

        }

        if($args->{cachedDataSource} eq 'remote'){

            $this->setDataStore( Cache::RemoteCache->new() ); 

        }


        if($args->{cachedDataSource} eq 'memd'){

            $this->setDataStore( Cache::MemedCache->new() ); 

        }

}
Run Code Online (Sandbox Code Playgroud)

但为了实现这一点,我必须这样做

use Cache::LocalCache;
use Cache::RemoteCache;
use Cache::MemedCache;
Run Code Online (Sandbox Code Playgroud)

有没有更好的方法来代理,而不必使用所有的包(如某种懒惰的负载)?

cjm*_*cjm 5

在您的示例中,您可以简单地使用require:

sub BUILD{
    my($this,$args) = @_;

        if($args->{cachedDataSource} eq 'local'){
            require Cache::LocalCache;
            $this->setDataStore( Cache::LocalCache->new() ); 
        }

        if($args->{cachedDataSource} eq 'remote'){
            require Cache::RemoteCache;
            $this->setDataStore( Cache::RemoteCache->new() ); 
        }

        if($args->{cachedDataSource} eq 'memd'){
            require Cache::MemedCache;
            $this->setDataStore( Cache::MemedCache->new() ); 
        }
}
Run Code Online (Sandbox Code Playgroud)

由于require是运行时操作,因此在实际需要之前不会加载该类.如果您的用户传递了类名,那么它会变得更复杂一些.您可能希望使用Module :: Load.