类(class) vs. 包(package) vs. 模块(Module)
类
- 在Perl 5语言里没有正式的有关"类"的定义。类只是一个面对对象编程(Object Oriented Programming)的概念。
包
- 包是Perl整合资源(函数、变量等)的一种方式。这些资源通常有着某种意义上的关联(也可以完全无关,perl不会限制你这样做。)
- 其命名空间的定义也不需要与目录/文件结构相匹配。(包可以定义于脚本内部,只限于该脚本调用。)
- 包的内容不非得是面对对象的。
模块
- 模块无非是一个外向(可公共调用)的包。
- 所以其命名空间的定义有与之相匹配的目录/文件结构。(如果你的模块是Foo::Bar::Baz,它需要有对应的目录/文件结构 "Foo/Bar/Baz.pm"。)
- 同包一样,模块的内容不非得是面对对象的。
Perl OO
Perl是一门自由、宽容的语言。一些规矩或范例不会强加给使用者,而是在使用者需要时随心调用。在面对对象的编程上亦不例外。
由于perl没有关于“类”的正式定义,就需要一种方式来声明一个对象和一个包的关联,从而使这个对象“进入”这个包的命名空间。bless()函数可以帮你完成这个操作。
bless $object, __PACKAGE__;
Perl的“类”函数与普通函数在功能上完全等同。只不过类函数的第一个参数必须是调用它的对象,即箭头运算符 "->"左边的那个值。也就是说,
- Class->method( @arg ) 等同于 Class::method( 'Class', @arg )
- $obj->method( @arg ) 等同于 (ref $object)::method( $obj, @arg ) ***
所以写构造函数时通常如下,注意bless语句并不是直接把对象bless成$class,为什么呢?
- package Foo;
- sub new
- {
- my $class = shift;
- my %this;
- ...
- bless \%this, ref $class || $class;
- }
其实原因在上面已经说明白了。(看上面 *** )这是因为类函数不仅可以通过类(包)的名字"Foo"来调用,即
也还可以通过一个"Foo"对象来调用,即
所以bless时要判断调用类函数的是类还是类对象,如果是通过类对象调用的,就bless成调用对象的那个类(ref $class);如果是通过类的名字调用的,直接bless成类就好了!
下面举个矩阵应用小例子(涉及到包和OO)。- #!/usr/bin/perl -w
- use strict;
- my $matrix = Matrix->new( [ 1, 2, 3 ], [ 4, 5, 6 ], [ 7, 8, 9] );
- print join "\n",
- 'before => ', $matrix->string,
- 'after => ', $matrix->transpose->string, "\n";
- package Matrix;
- sub new
- {
- my ( $class, @this ) = @_;
- bless \@this, ref $class || $class;
- }
- sub transpose
- {
- my $this = shift @_;
- my $column = @{ $this->[0] };
- for ( my $i = 0; $i < @$this; $i ++ )
- {
- for ( my $j = $i; $j < $column; $j ++ )
- {
- ( $this->[$i][$j], $this->[$j][$i] ) =
- ( $this->[$j][$i], $this->[$i][$j] );
- }
- }
- return $this;
- }
- sub string
- {
- my $this = shift;
- join "\n", map { join ' ', @$_ } @$this;
- }
- sub size
- {
- my $this = shift;
- my $row = @$this;
- my $col = @{ $this->[0] };
- return wantarray ? ( $row, $col ) : [ $row, $col ];
- }
- sub row
- {
- my ( $this, $row ) = @_;
- my $size = @$this;
- return undef if $row >= $size || $row < -$size;
- my @row = @{ $this->[$row] };
- return wantarray ? @row : \@row;
- }
- sub col
- {
- my ( $this, $col ) = @_;
- my $size = @{ $this->[0] };
-
- return undef if $col >= $size || $col < -$size;
- my @col = map { $_->[$col] } @$this;
- return wantarray ? @col : \@col;
- }
- sub copy
- {
- my $this = shift;
- my @that = map { [ @$_ ] } @$this;
- bless \@that, ref $this;
- }
- sub value
- {
- my ( $this, $i, $j, $x ) = @_;
- my ( $row, $col ) = $this->size();
- return $i >= $row || $i < -$row || $j >= $col || $j < - $col ? undef
- : defined $x ? ( $this->[$i][$j] = $x ) : $this->[$i][$j];
- }
- sub get { value( splice @_, 0, 3 ) }
- sub set { value( splice @_, 0, 4 ) }
- sub dimension { size( @_ ) }
- sub column { col( @_ ) }
- sub clone { copy( @_ ) }
- 1;
注意到这个package的最后一行。这是因为perl要求包的评价必须为真,所以最后一行是
阅读(5693) | 评论(0) | 转发(0) |