我应该如何访问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方法,但是,我直接访问一些变量的内部表示,例如:现实生活中的值是存储的