Perl 有几个很棒的对象系统,Moose 就是其中之一。但是 Moose 带有编译时开销,较小的应用程序可能不愿意为此付出代价,特别是对于某些 CGI 或命令行脚本。Moose 的功能非常丰富,您可能并不总是需要所有这些功能。
Mouse 来解救了!Mouse 是一个轻量级的对象系统,具有 Moose 功能的子集。其整个开发过程的目标是使其在语法上与 Moose 保持一致,因此如果您稍后需要切换到功能更强大的 Moose,您只需在代码库中将“Mouse”替换为“Moose”,一切都应该正常工作。
让我们快速了解一下 Mouse 的功能。为了便于讨论,这里有一个代码片段,定义了三个类
package Vehicle;
use Mouse;
has 'engine_type' => ( is => 'rw', isa => 'Str' );
has 'num_of_wheels' => ( is => 'rw', isa => 'Int' );
has 'max_passengers' => ( is => 'rw', isa => 'Int' );
has 'color' => ( is => 'rw', isa => 'Str' );
sub repaint {
my ($self, $new_color) = @_;
$self->color($new_color);
}
__PACKAGE__->meta->make_immutable();
package Bicycle;
use Mouse;
extends 'Vehicle';
has '+engine_type' => ( default => 'human' );
has '+num_of_wheels' => ( default => '2' );
has '+max_passengers' => ( default => '1' );
has 'basket_capacity' => ( is => 'rw', isa => 'Int', default => '0' );
before 'color' => sub {
my $self = shift;
$self->basket_capacity(0); # Take off the basket when we repaint
};
__PACKAGE__->meta->make_immutable();
package GoodsWagon;
use Mouse;
extends 'Vehicle';
has 'max_load_capacity' => ( is => 'rw', isa => 'Int' );
__PACKAGE__->meta->make_immutable();
一些基础知识
普通的 Perl 程序员会注意到,我没有在此代码中使用 use strict; use warnings;
,这几乎总是被鼓励的。Mouse 为您导入了这些,因此您不必这样做。
另外,请参阅在三个包的底部对 meta->make_immutable()
的调用?当您使一个类不可变时,您是在告诉 Mouse(或 Moose)您不会向该类添加任何更多的属性、方法或角色。这样做将加快运行时的速度,只是在首次加载类时会付出少量代价。建议大多数类都这样做,所以我在这里包含了它。
属性
三个包中的每一个都有一组属性,使用 has
关键字定义。因为它们在 is
属性参数中都是 'rw'
,所以 Mouse 会自动为属性创建一个读取器和一个写入器,对对象的用户可见
use Bicycle;
my $bike = Bicycle->new( color => 'Purple' );
print $bike->engine_type; # human
$bike->basket_capacity(4); # install a basket, with capacity 4
$bike->repaint('Blue'); # Bicycle inherits this sub from Vehicle.
# We could also just $bike->color('Blue');
在 Vehicle 类中,我定义了许多类型车辆共有的某些特征,但没有为它们设置任何值。您可以就此止步,但在应用程序中,我们希望拥有一些具有其他特征的特殊类型的车辆。
在 Bicycle 类中,我们为 engine_type
、num_of_wheels
和 max_passengers
设置了适用于自行车的默认值,并且我们还为 basket_capacity
设置了默认值,表明默认情况下未安装车筐。同时,在 GoodsWagon 中,我们定义了车辆的载货能力,这对于了解大型商用车辆很有价值。在两个子类中,我们都使用 extends
关键字继承了父类的属性特征。
您可以在这里做很多事情,例如使属性成为必需的,定义“构建器”子例程或方法来构造或计算属性,在设置属性时触发其他操作等等。
子程序继承
正如您在上面的示例中看到的,extend
其他类的类会继承它们的子程序。您可以通过将其写入子类来覆盖子程序,但在许多情况下,可能有一种更简单的方法:before
、after
和 around
。这些子程序在 before
的情况下在子程序或属性之前执行,在 after
的情况下在之后执行,在 around
的情况下在之前和之后都执行。我在 Bicycle 类中包含了一个 before
,它会在您更改颜色之前删除实例的车筐容量(您不希望在安装车筐的情况下重新粉刷自行车,对吧?)。聪明的是,您还可以使用 after
来执行您可能想要做的其他任务,例如润滑链条。
角色
最后,让我们看看角色。角色是 Mouse 中的类定义,它描述了另一个类可能做的事情或具有的共同特征。这是一个角色,我从 Moose 文档中获取并增强了它
package Breakable;
use Mouse::Role;
has 'is_broken' => ( is => 'rw', isa => 'Bool' );
sub break {
my $self=shift;
$self->is_broken(1);
}
sub fix {
my $self=shift;
$self->is_broken(0);
}
我们在这里添加了一个属性,该属性可以跨 Vehicle 及其所有子类型使用,并且(由于它非常通用)可以用于其他类型的机器或与车辆完全无关的其他对象。如果我们将 with 'Breakable';
添加到上面的 Vehicle 类中,那么我们可以这样做
use GoodsWagon;
my $wagon = GoodsWagon->new( color => 'Red', max_load_capacity => '4000' );
print $wagon->is_broken ? 'Broken down!' : 'Running fine!'; # Running fine!
$wagon->break;
print $wagon->is_broken ? 'Broken down!' : 'Running fine!'; # Broken down!
$wagon->fix;
当您想要拥有跨越多个类树的通用行为时,角色非常有用。如果 Vehicles 是您唯一想要以这种方式使其可破坏的东西,那么您只需将该功能放在 Vehicle 类中即可。
在 Perl 中,您有很多对象管理系统可供选择。对于小型项目,选择 Mouse 可以比运行 Moose 更快,并且如果项目增长,您可以轻松切换到 Moose 以获得更大的功能集。使用 Mouse 快速入门很容易;查看 Mouse 文档了解更多详情。
评论已关闭。