2009-08-04 64 views
1

我正在扩展一个模块,我想了解一些有关良好实践的提示。特别命名空间冲突:他们究竟是什么以及如何避免它们。我应该如何访问Perl子类中的实例数据?

扩展时,我不应该访问SUPER类中的变量,只能通过访问器或对象方法更改其状态?如果没有(或有限)访问者,该怎么办?我“允许”直接访问这些对象变量吗?

干杯!

回答

6

最好只通过访问者访问事物,因为这可以防止超类实现中的变化影响子类。你应该远离任何以底线开始的东西。这些东西对班上是私人的。尽量远离任何没有记录的东西。依靠这些东西会让你陷入麻烦。另外,考虑使用has-a与is-a的关系。

让我们来想象一个小部件类。这个类有名称和价格的成员(注意,这一切都不是特别好代码,我刚才扔的版本出来思考了一个例子的缘故):

package Widget; 

use strict; 
use warnings; 

sub new { 
    my $class = shift; 
    my %args = @_; 

    return bless { 
     price => $args{price} || 0, 
     name => $args{name} || "unkown", 
    }, $class; 
} 

sub price { shift->{price} } 
sub name { shift->{name} } 

1; 

你决定子类控件加配重块:

package Widget::WithWeight; 

use strict; 
use warnings; 

use base 'Widget'; 

sub new { 
    my $class = shift; 
    my %args = @_; 
    my $self = $class->SUPER::new(%args); 
    $self->{weight} = $args{weight} || 0; 
    return bless $self, $class; 
} 

sub weight { shift->{weight} } 

sub price_per_pound { 
    my $self = shift; 
    return $self->{price}/$self->{weight}; 
} 

1; 

现在想象一下,第一个模块的作者改变他/她对如何存储的价格头脑。或许正是存储为一个浮点数和作者意识到,把它作为便士的整数会更好:

package Widget; 

use strict; 
use warnings; 

sub new { 
    my $class = shift; 
    my %args = @_; 

    if ($args{price}) {   
     $args{price} =~ s/[.]//; 
    } 

    return bless { 
     price => $args{price} || "000", 
     name => $args{name} || "unkown", 
    }, $class; 
} 

sub price { 
    my $self = shift; 
    my $price = $self->{price}; 
    substr($price, -2, 0) = "."; 
    return $price; 
} 

sub name { shift->{name} } 

1; 

突然,你的测试将启动失败,但如果你已经使用了price访问,而不是,你会被这种改变所隔离。

+0

我没有使用_foobar方法,但是,我直接访问一些变量的内部表示,例如: 现实生活中的值存储为散列裁判是这样的: $自= { “财产” = > {objnum => NUM,type => TYPE,value => VALUE}, } 我应该*不*直接通过$ self访问'property',如$ self - > {property}?我应该只访问它,如果它有一个get_property()访问器? 在我的安装脚本中'需要'SUPER类模块的一个特定版本是一个白痴的事情吗? – 2009-08-04 14:01:20

+0

如果它们没有存储在带有下划线的散列(例如`$ self - > {_ property}`)中,那么它们是公平的游戏,但是访问方法是更安全的方法(保护您免受实施更改)。 – 2009-08-04 14:10:36

1

如果您从两个模块继承为一个模块并且它们都提供(导出)相同的子项,则可能发生名称空间冲突。

我建议你看看Moose,它是Perl的一个扩展,它为你提供了类和角色。如果您使用角色,则可以避免许多冲突。请参见http://www.iinteractive.com/moose/

Moose还为类变量生成自动访问器,使得从继承类访问它们更安全。

相关问题