我应该如何访问Perl子类中的实例数据?

我应该如何访问Perl子类中的实例数据?,perl,Perl,我正在扩展一个模块,我想要一些关于良好实践的提示。特别是名称空间冲突:它们到底是什么以及如何避免它们 扩展时,我是否应该不访问超类中的变量,而只通过访问器或对象方法更改其状态?如果没有(或有限的)访问者,该怎么办?是否允许我直接访问这些对象变量 干杯 最好只通过访问器访问内容,因为这样可以防止超类实现中的更改影响子类。你应该远离任何从车底开始的东西。那些东西是全班的隐私。尽量远离任何没有记录的东西。依赖这些东西会给你带来麻烦。此外,考虑使用HAS-A与IS-A关系。 让我们想象一个小部件类。这个

我正在扩展一个模块,我想要一些关于良好实践的提示。特别是名称空间冲突:它们到底是什么以及如何避免它们

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


干杯

最好只通过访问器访问内容,因为这样可以防止超类实现中的更改影响子类。你应该远离任何从车底开始的东西。那些东西是全班的隐私。尽量远离任何没有记录的东西。依赖这些东西会给你带来麻烦。此外,考虑使用HAS-A与IS-A关系。

让我们想象一个小部件类。这个类有name和price成员(注意,所有这些都不是特别好的代码,我只是为了一个示例,在没有考虑它的情况下抛出了一个版本):

您决定将小部件子类化以添加权重成员:

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
访问器,您将不会受到这种更改的影响。

最好只通过访问器访问内容,因为这样可以防止超类实现中的更改影响子类。你应该远离任何从车底开始的东西。那些东西是全班的隐私。尽量远离任何没有记录的东西。依赖这些东西会给你带来麻烦。此外,考虑使用HAS-A与IS-A关系。

让我们想象一个小部件类。这个类有name和price成员(注意,所有这些都不是特别好的代码,我只是为了一个示例,在没有考虑它的情况下抛出了一个版本):

您决定将小部件子类化以添加权重成员:

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
访问器,您将不会受到这种更改的影响。

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

我建议您看看Moose,它是Perl的一个扩展,为您提供类和角色。如果使用角色,可以避免许多冲突。看


Moose还为类变量提供自动访问器,使从继承类访问它们更加安全。

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

我建议您看看Moose,它是Perl的一个扩展,为您提供类和角色。如果使用角色,可以避免许多冲突。看


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

我不是从两个模块继承,所以这不是真正的问题。我听说过驼鹿的角色,它们看起来确实很有趣。但是,我正在扩展的模块不是我的(我不是作者),因此使用Moose为我的子类创建访问器没有任何好处。不过谢谢你的建议。注意,你可以用
Moose
对非
Moose
类进行子类化,所以没有什么可以阻止你使用它。不过,我还是建议你不要用普通的驼鹿。我的意思是:我正在创建类Foo::Bar,我没有创建Foo,这个类没有实现对它的一些数据的访问器。我会和作者联系,看看他为什么不想我戳那些数据。。。谢谢你给我的moosex提示!我不是从两个模块继承,所以这不是真正的问题。我听说过驼鹿的角色,它们看起来确实很有趣。但是,我正在扩展的模块不是我的(我不是作者),因此使用Moose为我的子类创建访问器没有任何好处。不过谢谢你的建议。注意,你可以用
Moose
对非
Moose
类进行子类化,所以没有什么可以阻止你使用它。不过,我还是建议你不要用普通的驼鹿。我的意思是:我正在创建类Foo::Bar,我没有创建Foo,这个类没有实现对它的一些数据的访问器。我会和作者联系,看看他为什么不想我戳那些数据。。。谢谢你给我的moosex提示!我没有使用_foobar方法,但是,我直接访问一些变量的内部表示,例如:现实生活中的值存储为如下哈希引用:$self={'property'=>{objnum=>NUM,type=>type,value=>value},}我是否应该像在$self->{property}中那样直接通过$self访问'property'?我应该只在它具有get_property()访问器时访问它吗?在我的安装脚本中“需要”一个超级类模块的特定版本会是一件愚蠢的事情吗?如果它们不是用一个下栏存储在哈希中(例如,
$self->{u property}
它们是公平的,但是访问器方法是一种更安全的方法(保护您不受实现更改的影响)。要求最低版本不是一个坏主意。我没有使用_foobar方法,但是,我直接访问一些变量的内部表示,例如:现实生活中的值是存储的