完全破坏Perl中对象的所有痕迹

时间:2015-08-05 19:43:54

标签: perl oop reference destroy

我正在编写一个Perl脚本,用于从不断变化的外部源获取数据。在从外部源添加或删除数据时,我希望Perl脚本中的数据结构能够镜像更改。我能够通过创建以类似方式存储数据的对象并在我尝试访问Perl脚本中的数据时同步这些对象中的数据来实现此目的。

这很好用,并获取添加到此外部源的任何新数据;但是,当删除任何数据时会出现问题。如果删除了任何数据,我希望销毁Perl脚本中对它的所有现有引用,以便用户不再尝试访问数据而不会引发错误。

我能想到的唯一方法是在确定数据不再存在时立即取消定义对数据的内部引用。然而,它似乎;当引用未定义时,它不会删除存储在引用位置的数据,它只会从保存引用的变量中删除数据。

这是一个演示我的问题的测试脚本:

#!/usr/bin/perl

# Always use these
use strict;
use warnings;

####################################################################################################
# Package to create an object
package Object;

use Moose;

# Define attributes
has 'name' => (is => 'ro', isa => 'Str', required => 1);

####################################################################################################
# Package to test with
package test;

# Create an object
my $object1 = Object->new('name' => 'Test Object');
print 'OBJECT1 NAME: '.$object1->name()."\n";

# Create another reference to the object
my $object2 = $object1;

# Print the name
print 'OBJECT2 NAME: '.$object2->name()."\n";

# Print both references
print "\n";
print "OBJ  : $object1\n";
print "OBJ2 : $object2\n";
print "\n";

# Undefine the reference to object2
undef $object2;

# Try to print both names
print 'OBJECT1 NAME: '.$object1->name()."\n";
print 'OBJECT2 NAME: '.$object2->name()."\n";

输出: Script Output

  

如何完全销毁对象的所有痕迹,以便任何试图访问它的数据都会导致错误?

编辑:

这是一个不同的例子,可以更好地解释我想要实现的目标。

说我有一个文件对象:

my $file = File->new();

现在我想获取该文件中的文本

my $text = $file->text();

现在我再次得到它(原因不明)

my $text2 = $file->text();

我希望能够修改$text,让它直接影响$text2的内容,并更改文件的实际text属性。

我基本上试图将变量绑定在一起,所以如果一个变化,它们都会改变。此外,如果删除一个,它们都将被删除。

这也意味着如果text属性发生了变化,$text1$text2也会随之改变以反映新值。

可以使用某种别名来完成吗?

2 个答案:

答案 0 :(得分:2)

Perl使用引用计数来“退出”数据。

您的计划正在做什么如下:

  1. 创建一个对象并指定对$object1
  2. 的引用
  3. 复制对$object2的引用并增加对象的引用计数
  4. 更改$object2的值并减少对象的引用计数。
  5. 最后,您仍然可以通过$object1保留对象,并且当您保持住它时,它的引用计数不会降至1以下。从技术上讲,当你的程序关闭时,$object1变量将在超出范围时被销毁,在该范围内,对象的引用计数将降至0并且perl将查找并尝试调用它的DESTROY方法。

    如果你真的想“看到”一个被破坏的项目,你可能想要研究定义一个DESTROY方法,该方法在对象销毁时打印出一条消息。这样你就可以“放开”你的最后一个参考,但仍然看到它的破坏。

答案 1 :(得分:2)

您无法释放仍在使用的对象。让对象本身跟踪它是否仍然有效。

sub new { 
   my ($class, $data) = @_;
   my $self = bless({}, $class);
   $self->{valid} = 1;
   $self->{data} = $data;
   return $self;
}

sub delete {
   my $self = shift;
   undef(%$self);
}

sub data {
   my $self = shift;
   croak("Invalid object") if !$self->{valid};
   $self->{data} = $_[0] if @_;
   return $self->{data};
}

示例:

my $o1 = Class->new('big_complex_data');
my $o2 = $o1;

say $o1->data();
say $o2->data();

$o1->delete();
say $o2->name();

输出:

big_complex_data
big_complex_data
Invalid object at a.pl line 39.