Perl封装了类变量?
我对perl很陌生,而且我遇到了家庭作业问题.我有一个带有类变量的对象,它计算创建的实例数.然后我有一个带有实例变量的子类.
我的第一个问题是,如何让用户隐藏类变量?我尝试使用闭包但无法弄清楚如何使继承工作.事实上,它是一个类变量使它变得更糟,因为增加它的代码执行了两次,它说我有两个实例,当我有一个.不完全确定它为什么会发生,但它是有道理的.我尝试使用标量,但变量再次没有正确递增.还没有尝试过“内外对象”而且我不确定我是否愿意,这似乎超出了我的想象.我觉得封装类变量与封装实例变量不同,但我找不到任何解释如何操作的东西. 我的第二个问题是,正如我所提到的,我无法使用继承来进行封装.使用闭包从子类调用超级构造函数时,您将获得对子例程的权限,因此没有办法(我知道)将实例变量添加到该子例程中. 这是我的基类: #!/usr/bin/perl -w use strict; package Base; my $count = 1; sub new { my $class = shift; my $self = { _Count => $count # not hidden }; $count++; # increment count bless $self,$class; return $self; } sub Count { # getter my $self = shift; return $self->{_Count}; } 1; 这是我的子类: #!/usr/bin/perl -w use strict; package Sub; use Base; our @ISA = qw(Base); sub new { my $class = shift; my $self = $class->SUPER::New(); $self->{_Name} = undef; # not hidden return $self; } sub Name { #getter/setter my($self,$name) = @_; $self->{_Name} = $name if defined($name); return $self->{_Name}; } 1; 解决方法
如果您使用的是裸Perl 5(而不是使用OO框架),那么执行类变量的常用方法是只对访问者可见的词法:
{ my $count = 0; sub Count { my ($self,$new_count) = @_; if (defined $new_count) { # NB only works if undef is not a legit value $count = $new_count; } return $count; } } $count仅在封闭块中可见;甚至在同一个类上的其他方法也看不到它.但任何人都可以用$base_obj-> Count或Base-> Count来操纵它,任何这样的操作都会影响共享变量. 您还可以使用闭包来提供真正隐藏的实例变量.除非你正在完成家庭作业的任意规则,否则这不值得做. package Base; sub new { my ($class,$name) = @_; die "Need name!" unless defined $name; my $age; return bless sub { my ($attribute,@args) = @_; if ($attribute eq 'name') { if (@args) { die "Attempt to set read-only attribute!"; } return $name; } if ($attribute eq 'age') { if (@args) { ($age) = @args; } return $age; } die "Unknown attribute $attribute"; } => $class; } sub name { my ($self,@args) = @_; return $self->(name => @args); } sub age { my ($self,@args) = @_; return $self->(age => @args); } 这里发生的事情是,新的返回的祝福子关闭了两个词汇,$name和$age.当新的返回时,那些词法超出范围,从那一点开始访问它们的唯一方法是通过关闭.闭包可以检查其参数以允许或拒绝访问它所拥有的值.只要它永远不会返回引用,就可以确保它只能直接访问这些变量. 这也适用于继承,没有太多额外的细微之处: package Derived; use base 'Base'; sub new { my ($class,$name,$color) = @_; my $base_instance = $class->SUPER::new($name); return bless sub { my ($attribute,@args) = @_; if ($attribute eq 'color') { if (@args) { ($color) = @args; } return $color; } # base class handles anything we don't,possibly by dying return $base_instance->($attribute,@args); } => $class; } 这模拟了基本和派生类实例数据具有不同存储的语言,可以在本地处理请求,也可以将其传递给已添加到闭包中的基类实例.更深的继承树将导致闭包闭合闭包的闭包,每个闭包都可选地关闭该特定类所需的实例变量. 这是一个相当大的混乱,很难检查和调试,这就是为什么我要再强调一次你永远不应该这样做.但是理解它是非常有用的,为此我将你推荐给SICP. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |