加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

Perl封装了类变量?

发布时间:2020-12-15 23:27:18 所属栏目:大数据 来源:网络整理
导读:我对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.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读