在perl中如何使用公共关键字?

在perl中如何使用公共关键字?,perl,Perl,我见过这样的代码 package xyz; # putting the module inside its own pair of braces { public _foo => my %_foo; public _bar => my %_bar; # some subroutines.. } 1; 我的问题是公开声明的确切含义是什么_foo=>My%\u foo; 我的意思是如何使用public关键字,为什么我们要使用大箭头来分配另一个哈希 任何帮助

我见过这样的代码

package xyz;

# putting the module inside its own pair of braces
{
    public _foo => my %_foo;
    public _bar => my %_bar;

    # some subroutines..

}
1;
我的问题是公开声明的确切含义是什么_foo=>My%\u foo; 我的意思是如何使用public关键字,为什么我们要使用大箭头来分配另一个哈希

任何帮助都将不胜感激。

哦,你正在使用吗

在这种情况下,它不是一个关键字,它实际上是一个子例程。它在包中设置一个存储变量,用作类属性

基本上,由内而外对象是在Perl中实现真正封装的一种方法。通常,Perl对象将其值存储在散列引用中,然后将散列引用返回给用户,如下所示:

package Foo;
use strict;
use warnings;

sub new {
    my ($class, %args) = @_;
    return bless {
        foo => $args{foo},
        bar => $args{bar},
    }, $class;
}

sub get_foo {
    my $self = shift;
    return $self->{foo};
}

sub get_bar {
    my $self = shift;
    return $self->{bar};
}

1;
package Foo;
use strict;
use warnings;
use Scalar::Util qw/refaddr/;
{
    my %_foo_of;
    my %_bar_of;

    sub new {
        my ($class, %args) = @_;
        # create a reference to an anonymous scalar.
        my $instance = \do { my $anon_scalar }; 
        $_foo_of{ refaddr $instance } = $args{foo};
        $_bar_of{ refaddr $instance } = $args{bar};
        return $instance;
    }

    # we have to manually delete these since they don't go out of scope
    # automatically like standard Perl classes do!
    sub DESTROY {
        my $self = shift;
        delete $_foo_of{ refaddr $self };
        delete $_bar_of{ refaddr $self };
    }

    sub get_foo {
        my $self = shift;
        return $_foo_of{ refaddr $self };
    }

    sub get_bar {
        my $self = shift;
        return $_bar_of{ refaddr $self };
    }
}

1;
如您所见,类所包含的详细信息实际上会返回给用户!他们可以在不使用访问器的情况下随心所欲地使用它。Whups

由内而外的对象使用这样一个事实,即包内的词汇变量(例如
my
variables)永远无法在其范围之外看到。它利用了这样一个事实,即每个唯一标量引用都有一个唯一的地址,这给了我们一个进入散列的唯一键,允许我们为类数据提供一个唯一的、受限的存储。基本模式如下所示:

package Foo;
use strict;
use warnings;

sub new {
    my ($class, %args) = @_;
    return bless {
        foo => $args{foo},
        bar => $args{bar},
    }, $class;
}

sub get_foo {
    my $self = shift;
    return $self->{foo};
}

sub get_bar {
    my $self = shift;
    return $self->{bar};
}

1;
package Foo;
use strict;
use warnings;
use Scalar::Util qw/refaddr/;
{
    my %_foo_of;
    my %_bar_of;

    sub new {
        my ($class, %args) = @_;
        # create a reference to an anonymous scalar.
        my $instance = \do { my $anon_scalar }; 
        $_foo_of{ refaddr $instance } = $args{foo};
        $_bar_of{ refaddr $instance } = $args{bar};
        return $instance;
    }

    # we have to manually delete these since they don't go out of scope
    # automatically like standard Perl classes do!
    sub DESTROY {
        my $self = shift;
        delete $_foo_of{ refaddr $self };
        delete $_bar_of{ refaddr $self };
    }

    sub get_foo {
        my $self = shift;
        return $_foo_of{ refaddr $self };
    }

    sub get_bar {
        my $self = shift;
        return $_bar_of{ refaddr $self };
    }
}

1;
哎哟。很多样板。更多的模板工作。讨厌

现在让我们用
Class::InsideOut
来看看它

package Foo;
use strict;
use warnings;
use Class::InsideOut qw/new public/;

public foo => my %foo;
public bar => my %bar;

1;
完成了

如果需要,您可以创建一个更复杂的
new
子例程,但这会自动设置一个默认的
new
子例程,用于从命名参数初始化
foo
bar


类::InsideOut使您不必做样板文件之类的事情。它为您创建访问器,为您创建匿名标量,为您创建析构函数,并为您提供nice
id
关键字,而不是refaddr。除此之外,一切都是一样的。它只是去除了一些您通常必须处理的样板文件,使得由内而外的类易于使用(而且很有趣!)。

您确定这是Perl吗?它看起来不像我见过的任何Perl。可能是perl 6。这不是有效的perl5代码,除非使用第三方模块添加一些新语法(例如MooseX::Declare)。你能为上下文提供更多的代码吗?是的,科林和以太说过。在阅读问题时,我的眼睛确实做了一个
O.O
。正如@Ether所说:“-第5行的语法错误,靠近“public\u foo”执行-由于编译错误而中止。”(这是“我见过这样的代码”问题的问题。“like”通常还不够“like”!:)嗨,Robert,你说得对,我使用的是Class::InsideOut qw(公共注册);我是Perl新手,这就是为什么我对InsideOut一无所知的原因。这段代码与我在教科书中读到的完全不同,就像其他人评论的一样。谢谢你的回答。现在我可以弄明白了!Arun