2008年10月12日星期日

perl Moose::Cookbook::Basics::Recipe1

eg:

package Point;
use Moose;

has 'x' => (isa => 'Int', is => 'rw', required => 1);
has 'y' => (isa => 'Int', is => 'rw', required => 1);

sub clear {
my $self = shift;
$self->x(0);
$self->y(0);
}

package Point3D;
use Moose;

extends 'Point';

has 'z' => (isa => 'Int', is => 'rw', required => 1);

after 'clear' => sub {
my $self = shift;
$self->z(0);
};

....

# hash or hashrefs are ok for the constructor
my $point1 = Point->new(x => 5, y => 7);
my $point2 = Point->new({x => 5, y => 7});
my $point3d = Point3D->new(x => 5, y => 42, z => -5);


和perl5里面非常相似,类都放在一个声明的package里面,use Moose自动为我们添加use strict和use Waring,同时导入缺省的函数和关键字,并自动创建构造器

第一个关键字

has 'x' => (isa => 'Int', is => 'rw', required => 1);

为类创建一个名为x的属性,isa代表这是一个Int类型的变量,rw代表可读写,required代表创建类的实例的时候,必须提供这个变量值。
之后可以创建类的方法了,它只是一个子函数而已

sub clear {
my $self = shift;
$self->x(0);
$self->y(0);
}


借着来我们定义了子类Point3D,在子类中通过关键字extend来声明父类

extends 'Point';

extends和use base的功能很像,但有点不同的是extends覆盖了@ISA数组,而use base是把参数添加到@ISA数组
接下来创建类Point3D的新属性x
has 'z' => (isa => 'Int', is => 'rw', required => 1);

这和x,y没什么区别
after关键字声明了Moose的一个特性:方法修改器
 after 'clear' => sub {
my $self = shift;
$self->z(0);
};

当从类Point3D中调用clear是,这个定义的函数会运行,之所以称为关键字after,是由于这个修改器在真正定义的函数后在被调用的。
从某种意义上来说这就是一个函数的继承

我们当然还有其他的方法做到这些,因为这是"perl"
比如:

sub clear {
my $self = shift;
$self->SUPER::clear();
$self->z(0);
}

再比如使用关键字override

override 'clear' => sub {
my $self = shift;
super();
$self->z(0);
};

据说是可以让你像ruby一样使用父类函数,可惜不懂ruby

然后就可以使用我们所写的类了

my $point1 = Point->new(x => 5, y => 7);
my $point2 = Point->new({x => 5, y => 7});

my $point3d = Point3D->new(x => 5, y => 42, z => -5);


注意:Moose里面的类都是一个hasn引用

所谓脚注:

1:Moose定义的数据类型
很多,去这里看 Moose::Util::TypeConstraints
2:Moose的extends支持多重继承
3:没看太懂,大约是使用某种方法Moose可以支持非hashref类型的类
文档支持在这里 Moose::Util::TypeConstraints

没有评论: