老实说,我不确定 Perl 的原始 OO 原语的知识对于编写新代码有多大价值。我已经很长时间没有在我的代码中使用@ISA 或“使用基础”或“祝福”了;我做的任何 OO 都是通过 Moose MOP。(当然,我会使用 rebless 实例,但我使用 $meta->rebless_instance 而不仅仅是“bless”。更简洁!)
无论如何,我会先自学Moose。它很容易上手并立即获得成效,随着您对 Perl 和一般编程的熟练程度越来越高,您可以了解细节。
举个例子:
#!/usr/bin/env perl
use strict;
use warnings;
use feature ':5.10'; # for 'say'
use MooseX::Declare;
class Point {
has [qw/x y/] => ( is => 'ro', isa => 'Num', required => 1 );
method new_from_ordered_pair(ClassName $class: Num $x, Num $y){
return $class->new( x => $x, y => $y );
}
method distance(Point $a: Point $b){
return sqrt( ($a->x - $b->x)**2 + ($a->y - $b->y)**2 );
}
}
my $origin = Point->new_from_ordered_pair(0,0);
my $point = Point->new_from_ordered_pair(3,4);
say '(3,4) is '. $point->distance($origin). ' units away from the origin.';
请注意如何不再与 Perl 的实现细节发生争执。您可以轻松地担心程序的细节,而不用担心如何在 Perl 中进行 OO。您甚至不必制作“Point.pm”文件,您可以将类定义内联。
我还认为几乎所有程序员都可以立即理解这段代码——即使是不熟悉 Perl 或 Moose(或 MooseX::Declare)细节的程序员。
(顺便说一句,这个例子在方法签名中使用“:”语法有点奇怪。通常,你会得到一个名为 $self 的你自己的实例作为第一个参数。如果你在签名中的 : 之前提供其他东西,你可以更改变量的类型和名称。我还写了“new_from_ordered_pair”,这样您就不必x => $x, y => $y
每次都输入新的参数。这只是我认为很好的糖;这里没有发生任何神奇的事情。)
最后,您可以在这里“免费”获得很多东西。试试这些,并注意有用的错误消息:
Point->new; # x is required
Point->new_from_ordered_pair('foo', 'bar'); # x needs to be a number
$point->distance('some string'); # $b needs to be a Point
您可以免费获得所有这些,它使您的程序调试更加容易。没有理由避免它,它确实让编程更有趣(而且它让你的程序更可靠......免费!)
哦,还有一件事。使用 Moose,您可以内省您的课程。这可能并不立即重要,但拥有它可能会很好。打开 Devel::REPL,输入 'do "test.pl"' 以加载 Point 类,然后说如下内容:
map { $_->name } Point->meta->get_all_attributes;
结果是['x', 'y']
。没有源代码,您可以找出该类具有哪些属性。尝试使用“普通的”Perl OO 来做到这一点。(这种东西使丰富的 MooseX:: 命名空间成为可能。您可能不需要自省,但您将享受使用来自 CPAN 的可靠模块的能力。)