Mouse:小型项目的省时对象系统

Mouse 是 Moose 的轻量级 Perl 替代方案,仅需基本功能。
278 位读者喜欢这篇文章。
3 cool machine learning projects using TensorFlow and the Raspberry Pi

Opensource.com

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_typenum_of_wheelsmax_passengers 设置了适用于自行车的默认值,并且我们还为 basket_capacity 设置了默认值,表明默认情况下未安装车筐。同时,在 GoodsWagon 中,我们定义了车辆的载货能力,这对于了解大型商用车辆很有价值。在两个子类中,我们都使用 extends 关键字继承了父类的属性特征。

您可以在这里做很多事情,例如使属性成为必需的,定义“构建器”子例程或方法来构造或计算属性,在设置属性时触发其他操作等等。

子程序继承

正如您在上面的示例中看到的,extend 其他类的类会继承它们的子程序。您可以通过将其写入子类来覆盖子程序,但在许多情况下,可能有一种更简单的方法:beforeafteraround。这些子程序在 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 文档了解更多详情。

User profile image.
Ruth Holloway 长期以来一直担任系统管理员和软件开发人员,早在 VAX 11/780 上就开始了她的职业生涯。她职业生涯的大部分时间(到目前为止)都在为图书馆的技术需求服务,并且自 2008 年以来一直是 Koha 开源图书馆自动化套件的贡献者。Ruth 目前是 Clearbuilt 的 Perl 开发人员和项目负责人。

评论已关闭。

Creative Commons License本作品根据 Creative Commons Attribution-Share Alike 4.0 International License 获得许可。
© . All rights reserved.