如何在Perl对象上组织私有方法?

时间:2017-01-06 23:43:44

标签: perl oop

处理用户不会调用的方法的正确方法是什么?例如,如果用户调用方法,从驱动程序脚本中说出do_stuff(),并且如果do_stuff()依赖于其他子例程,那么最好从do_stuff()方法中调用这些子方法作为如下:

sub do_stuff {
    my ( $self, %arg ) = @_;
    #does it things
    #and then calls the private sub as follows
    _private_sub( $self, %arg );
}

4 个答案:

答案 0 :(得分:4)

据我所知,没有"正确"办法。 Perl并没有提供隐藏功能的能力,至少我曾遇到过这种功能。我所做的是使用一个命名标准,我用一个下划线启动仅限内部的函数名称,并清楚地记录它们永远不会被外部调用者调用。

编辑:其他答案引发了一个想法。在每个私有方法中,您可以检查"调用者()"的结果。如果调用者是本地模块以外的任何人,则函数和中止。老实说,我个人不会遇到麻烦,但如果由于某些原因它对你来说真的很重要,那就会强调这些方法的私密性。

答案 1 :(得分:3)

如果您的do_stuff方法需要您应该保留的功能,那么#34;私有"然后一定要在其中调用_private_sub。这正是它的目的。当然,拥有一个私人"私人"是一个惯例问题,因为它无法执行。

我想提一下使用私有子代码

的代码
my $_private = sub { ... };  # must be at least predeclared

sub do_stuff {
    my ($self, %arg) = @_;
    # ...
    my $from_private = $self->$_private->(@args);    # or
    my $more_private = $_private->($self, @args);
}

语法很奇怪,但肯定警告用户它是私有方法。这使得子类很难继承,这要归功于mob强调这一点。

第二次调用使用$_private作为函数而不是方法,因此我们必须在需要时传递对象。这进一步警告不要使用它。然后它也没有经历正常的方法查找过程(因此稍快一点),这是一个很清楚的事情。

我对这个问题究竟是什么有点不确定。

如果是关于是否使用"私人"你的代码中的子程序,然后真的没有公认的最佳实践。它们非常有用,但它们并非真正私密。我自由地使用它们。

完整的答案是使用MooseMoo或其他模块。

答案 2 :(得分:1)

$self->_private_sub(...)相反?在我看来,$obj->_method符号总是与作用于类实例的函数一起使用,其他类型的调用总是用于其他类型的函数。

但是,如果你是偏执狂,为什么不使用一种非传统的方式来填充你的论点,这会让那些试图以面向对象的方式使用私有方法的人感到困惑呢?

sub do_stuff {
    my ( $self, %arg ) = @_;
    ...
    _private_sub( %arg, $self );
}

sub _private_sub {
    my $self = pop;
    my %args = @_;
    ...
}

答案 3 :(得分:1)

到目前为止,您收到的所有答案都表示无法完成。但它可以 - 在Perl 5.18及更高版本中。请参阅section on lexical subroutines in perldoc perlsub

  

词汇子程序

     

警告:词法子程序仍处于试验阶段。在将来的Perl版本中可能会修改或删除该功能。

     

词法子程序仅在let boston: [String: Any] = ["title": "Boston, MA", "latitude": 39.713054, "longitude": -88.632398] locations.append(boston) 编译指示下可用,它会产生警告,除非" experimental :: lexical_subs"警告类别已禁用。

     

从Perl 5.18开始,您可以使用use feature 'lexical_subs'my声明私有子例程。与状态变量一样,州关键字仅在stateuse feature 'state'或更高版本下可用。

     

这些子例程仅在声明它们的块中可见,并且仅在声明之后:

use 5.010
     

要从子程序本身内部使用词法子程序,必须预先声明它。 no warnings "experimental::lexical_subs"; use feature 'lexical_subs'; foo(); # calls the package/global subroutine state sub foo { foo(); # also calls the package subroutine } foo(); # calls "state" sub my $ref = \&foo; # take a reference to "state" sub my sub bar { ... } bar(); # calls "my" sub 子例程定义语法尊重任何先前的sub foo {...}my sub;声明。

state sub;