如何使用插件编写Perl对象?
如何使用可扩展代码编写Perl对象?我在考虑驱动程序或一些配置,用户可以在其中传递字符串“Classname::Class”或其他内容。谢谢 例如,对于图形类:如何使用插件编写Perl对象?,perl,Perl,如何使用可扩展代码编写Perl对象?我在考虑驱动程序或一些配置,用户可以在其中传递字符串“Classname::Class”或其他内容。谢谢 例如,对于图形类: my $spg = Graph::ShortestPathGraph->new; $spg->Algorithm( "Graph::DFS" ); $spg->solve; $spg->Algorithm( "Graph::BFS" ); $spg->solve; 可能会帮助你实现你想要的。这里是一个简
my $spg = Graph::ShortestPathGraph->new;
$spg->Algorithm( "Graph::DFS" );
$spg->solve;
$spg->Algorithm( "Graph::BFS" );
$spg->solve;
可能会帮助你实现你想要的。这里是一个简单的自制示例。一旦您理解了它,您就可以继续学习旨在消除这种单调乏味的模块:
#!/usr/bin/perl
package Me::Mine;
use base 'Class::Accessor';
__PACKAGE__->mk_accessors( qw( dumper ) );
sub dump {
my $self = shift;
my $dumper = $self->dumper;
eval "require $dumper";
print "Dumping using $dumper\n", $dumper->Dump([ $self ]);
return;
}
package main;
use strict; use warnings;
my $me = Me::Mine->new;
my $you = Me::Mine->new;
$me->dumper('Data::Dumper');
$you->dumper('YAML');
$_->dump for $me, $you;
输出:
Dumping using Data::Dumper
$VAR1 = bless( {
'dumper' => 'Data::Dumper'
}, 'Me::Mine' );
Dumping using YAML
--- YAML
---
- !!perl/hash:Me::Mine
dumper: YAML
使用Data::Dumper进行转储
$VAR1=祝福({
“转储程序”=>“数据::转储程序”
}“我的……”;
使用YAML进行倾倒
---亚马尔
---
- !!perl/hash:Me::Mine
翻车机:YAML
如何编写可扩展代码
有计划。假设您正在编写一个用于绘制曲线的算法
一组点。你需要这些点的一个来源,一个用来绘图的地方
它们,以及一种插值不在
设定
(请注意,假设“图形”在这里的意思是“图表”,而不是
离散数学意义上的图形。)
让我们定义表示这些操作的角色。来源
积分必须能够为我们提供以下积分:
package Graphomatic::PointSource;
use Moose::Role;
requires 'get_points'; # return a list of points
1;
绘图仪必须允许我们绘制点:
package Graphomatic::Plot;
use Moose::Role;
requires 'plot_point'; # plot a point
requires 'show_graph'; # show the final graph
1;
当给定两个相邻点时,插值器必须给我们一个点:
package Graphomatic::Interpolate;
use Moose::Role;
requires 'interpolate_point';
1;
现在,我们只需要根据这些来编写我们的主应用程序
角色:
现在只需定义一些源代码实现。
让我们从文件中读取点:
package Graphomatic::PointSource::File;
use Moose;
use MooseX::FileAttribute;
# ensure, at compile-time, that this class is a valid point
# source
with 'Graphomatic::PointSource';
has_file 'dataset' => ( must_exist => 1, required => 1 );
sub get_points {
my $self = shift;
return parse $self->dataset->slurp;
}
1;
并打印到Z窗口系统:
package Graphomatic::Plot::Z;
use Moose;
use Z;
with 'Graphomatic::Plot';
has 'window' => ( is => 'ro', isa => 'Z::Window', lazy_build => 1);
sub _build_window { return Z->new_window }
sub plot_point {
my ($self, $point) = @_;
$self->window->plot_me_a_point_kthx($point->x, $point->y);
}
sub show_plot {
my $self = shift;
$self->window->show;
}
1;
然后用随机数生成器进行插值(嘿,我很懒,而且
不查找双三次插值:P):
现在,我们可以将所有部件组装成一个工作程序:
use Graphomatic::PointSource::File;
use Graphomatic::Plot::Z;
use Graphomatic::Interpolate::Random;
my $graphomatic = Graphomatic->new(
source => Graphomatic::PointSource::File->new(
file => 'data.dat',
),
plot => Graphomatic::Plot::Z->new,
interpolate => Graphomatic::Interpolate::Random->new,
);
$graphomatic->run;
现在,您可以干净地自定义任何零件,而不影响
其他部分,只需实现“完成”所需任务的新类
角色。(如果他们说‘有……’,但不符合要求,
一旦加载类,就会出现错误。如果尝试
将实例用作不“执行”正确角色的参数
他会死的
输入安全,这是一件美妙的事情。)
至于处理配置文件,只需以某种方式读取名称和参数,
然后:
my $interpolate_class = get_config('interpolate_class');
Class::MOP::load_class($interpolate_class);
my $interpolate = $interpolate_class->new( %interpolate_class_args );
my $graphomatic = Graphomatic->new( interpolate => $interpolate, ... );
这是一种很好的自动化方法。签出,以及
如果该类不存在,则抛出一个错误。但是,如果您想自己创建Algo类,那么制作它们可能会更好
有大量使用Moose预先制作的解决方案可以解决此问题,请查看CPAN。请提供一个更详细的示例,说明您试图解决的问题。一些伪代码会很好。不要执行
eval“require$dumper”
。这使我成为一个悲伤的弗里多。将模块名转换为其文件名并不难。甚至还有一个方便的CPAN项目:@friedo你能扩展一下吗?我的意思是,这是一次性代码,只是为了说明一种技术,因此没有错误/参数检查,但是eval“require$dumper”
有什么特别的错误(如?推荐的那样,我有一个(可能是不合理的)厌恶所有形式的字符串eval
,除非它是绝对必要的。在这种情况下,它不是必要的,因为很容易获得模块文件名,所以您可以使用my$mod_file=module_path$dumper;require$mod_file;
。
use Graphomatic::PointSource::File;
use Graphomatic::Plot::Z;
use Graphomatic::Interpolate::Random;
my $graphomatic = Graphomatic->new(
source => Graphomatic::PointSource::File->new(
file => 'data.dat',
),
plot => Graphomatic::Plot::Z->new,
interpolate => Graphomatic::Interpolate::Random->new,
);
$graphomatic->run;
my $interpolate_class = get_config('interpolate_class');
Class::MOP::load_class($interpolate_class);
my $interpolate = $interpolate_class->new( %interpolate_class_args );
my $graphomatic = Graphomatic->new( interpolate => $interpolate, ... );
package MyClass;
use Moose;
use MooseX::Types::LoadableClass qw/ClassName/;
has 'algo' => (
is => 'ro'
, isa => ClassName
, coerce => 1
);
sub solve {
my $self = shift;
my $algo = $self->algo->new;
# stuff using algo
}
## These work:
Graph::ShortestPathGraph->new({ algo => 'Graph::DFS' })->solve;
Graph::ShortestPathGraph->new({ algo => 'Graph::BFS' })->solve;
## As does this:
my $gspg = Graph::ShortestPathGraph->new;
$gspg->algo('Graph::BFS');
$gspg->solve;