Perl5 中的 OO 范式和封装的实例变量



我需要一种方法在Perl中制作真正封装的变量,而无需使用Moose等任何框架,以便您只能通过getters和setter访问实例变量。应该有私有实例变量。

子例程分别方法不是问题,因为您可以定义它们,以便它们只能通过实例分别引用来使用。但是您始终可以通过包名称访问的变量,例如类变量。

有什么办法可以防止这种情况吗?

听起来您正在尝试阻止人们通过访问器以外的方式访问实例变量; 对吗?

Perl 是一种适合有礼貌的人的语言,你阻止程序员做你不希望他们做的事情的方式就是要求他们不要这样做。是的,有黑客攻击,这里最明显的一个是使每个对象成为一个闭包(这是Perl Journal上关于它的文章),但几乎总是有解决方法,所以你将无法阻止坚定的无礼黑客

拉里·沃尔(Larry Wall)的一个很好的归因是这一点,它很好地解释了我的观点。

Perl 并不迷恋强制隐私。它宁愿你远离它的客厅,因为你没有被邀请,而不是因为它有霰弹枪。

人们试图用由内而外的物体来实现这种事情。大卫·戈尔登的演讲完美地解释了它:

  • 内而外的对象由荷兰Perl黑客Abigail在2002年首次提出

  • 2002年春季 – 在 Amsterdam.pm 首次提及,

  • 2002年6月28日 – YAPC NA"做OO的两种替代方法"

  • 2002年7月1日——首次提及Perlmonks

  • 最近随着Damian Conway的Perl Best Practices的出版而受到关注(臭名昭著?)作为推荐的最佳实践

  • 尽管它们有好处,但它们带来了巨大的复杂性,并且并不普遍受欢迎

有许多模块试图促进这种类型的编程。

我觉得它们相当麻烦,而且它们已经失宠了。

你也可以在perldoc perlobj中找到它们:

过去,Perl 社区尝试了一种称为"由内而外的对象"的技术。由内而外的对象将其数据存储在对象的引用之外,根据对象的唯一属性(如其内存地址)而不是对象本身进行索引。这样做的好处是强制封装对象属性,因为它们的数据不存储在对象本身中。

这种技术流行了一段时间(并在Damian Conway的Perl Best Practices中被推荐),但从未被普遍采用。CPAN 上的 Object::InsideOut 模块提供了这种技术的全面实现,您可能会在野外看到它或其他由内而外的模块。

要做真正的私有变量,你应该使用闭包:

{
    my $x;
    sub get {
        return $x;
    }
    sub set {
        $x =  shift;
    }
}
set( 3 );
print get(); # prints 3
print $x; # ERROR
# Example with objects
package Class;
sub new {
    bless {}, 'Class';
}
{
    my $storage =  {};
    sub get {
        $self =  shift;
        return $storage->{ "$self" };            
    }
    sub set {
        $self =  shift;
        $storage->{ "$self" } =  shift;
    }
}
package main;
print Class::x; #ERROR
$z = Class::new();
$z->set( 3 );
$y = Class::new();
$y->set( 5 );
print $y->get(); # 5
print $z->get(); # 3

$x是块的本地。除了setget之外,没有人可以访问它。
"$self"就像"Class=HASH(0x1cf9160)"。因为每个对象都有自己的地址,在内存中"$self"永远不会冲突。

但实际上,在其他情况下,您不需要这样做,这将是您车轮上的一根棍子

最新更新