如何在面向对象的Perl中定义私有或内部方法?

enn*_*ler 8 oop perl private-methods

我正在使用Damian Conway的"由内而外"的对象,如他所描述的那本精彩的书Perl Best Practices,用于在我的客户端构建面向对象的安全系统接口.我想在我的模块中使用内部帮助器方法,我通常将其指定为"_some_method".但是,这似乎打破了封装,因为它们可以通过包名直接调用.有没有办法让这些方法真正私密?举个例子,

use SOD::MyOOInterface;

my $instance1 = SOD::MyOOInterface->new();
$instance1->_some_method;  #this produces an error: 
SOD::MyOOInterface::_some_method;   # this results in a 
                                    # successful method call 
Run Code Online (Sandbox Code Playgroud)

显然我不希望_some_method的直接调用成功.有什么方法可以保证吗?

Ran*_*rtz 11

package Foo;

## declare inside-out hashes here:

my %attr_a;
my %attr_b;

## declare private methods here

my $private_1 = sub {
  my $self = shift;
  # can use $attr_a{$self} here...
  ...
};

my $private_2 = sub {
  my $self = shift;
  ... 
};

## public methods here

sub new { ... }

sub public_1 {
  my $self = shift;
  # can access attributes here
  # can call private methods too, with slightly odd syntax:
  my $result = $self->$private_1(@args);
  ...
}

1;
Run Code Online (Sandbox Code Playgroud)


Mic*_*man 6

有点.您无法隐藏已安装到符号表中的子例程,但您可以使用词法变量来保存对匿名子例程的引用:

package SOD::MyOOInterface;

my $some_method = sub { ... }

$some_method->();
Run Code Online (Sandbox Code Playgroud)

因为$some_method只在实现类的文件中可见,所以子程序不能在外部调用.缺点是它不能作为方法调用,必须作为函数调用.如果要将其用作方法,则必须显式传递对象引用:

$some_method->($obj, @args);
Run Code Online (Sandbox Code Playgroud)

  • 如果你正在使用由内而外的对象,你已经在做"hackish"OO.通过CODE引用隐藏私有方法似乎很适合. (3认同)
  • 您可以将其称为方法.`$ self - > $ some_method()`工作正常.当然,你需要在公共方法中使用`$ self`. (2认同)

Eva*_*oll 6

不要将PBP用于对象实践.这是非常古老的.事实上,现在关于Perl和对象的最佳实践可以在Moose中找到,这对于Perl来说几乎是必须的.

简而言之,Perl模糊命名空间和类的方式可以在类上静态调用大多数方法.这不是坏事,只是不记录它.没有理由想要将方法密封到实例中.没有私人方法有点令人讨厌,但不依赖于无证方法的惯例是如此强烈,它已经足够我们的社区.

特征实际上是一个可以在运行时编译成对象的角色(不允许实例化).这将进一步模糊典型用户的方法来源(因为它们不会在原始类中),但它会以运行时成本出现.有关特征的更多信息,请参阅MooseX :: Traits.

前置下划线是一个很好的惯例,进一步说明该方法是专用于窥视眼睛.

就好像你真的想推动此问题的最后一个音符,你也许可以创建使用类:: MOP ::讲座> create_anon_class这些方法匿名类()

  • 将内向外对象视为基于hashref的对象是微不足道的.Scrottie有一个CPAN模块来做​​到这一点.所以基本上,内部输出技术不会比命名方法"_foo"更模糊你的界面. (2认同)