2015-08-05 4 views
1

Я пишу скрипт Perl, который получает данные из изменяющегося внешнего источника. Поскольку данные добавляются или удаляются из этого внешнего источника, я хотел бы, чтобы структуры данных в моем скрипте 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


Как я могу полностью уничтожить все следы объекта, так что любая попытка получить доступ к его данным приведет к ошибке?


EDIT:

Вот другой пример, который может лучше объяснить, что я пытаюсь достичь.

Скажем, у меня есть файл объект:

my $file = File->new();

Теперь я хочу, чтобы получить текст в этом файле

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

Теперь я снова (по неизвестной причине)

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

Я хочу, чтобы иметь возможность изменять $text и напрямую влиять на содержимое $text2, а также изменять фактический атрибут text файла.

Я в основном пытаюсь связать переменные вместе, поэтому, если они меняются, все они меняются. Кроме того, если удалять, все они будут удалены.

Это также означает, что при изменении атрибута text$text1 и $text2 также изменились бы с ним, чтобы отразить новое значение.

Это может быть сделано с использованием псевдонима какого-то рода?

+0

Так что вы хотите '$ object1' стать' undef' после ввода 'UNDEF $ object2'? –

+0

Да, это то, что я ищу. – tjwrona1992

+0

См. Также [Как вы явно уничтожаете объект в Perl?] (Http://stackoverflow.com/questions/10772220/how-do-you-explicitly-destroy-an-object-in-perl) –

ответ

2

Perl использует подсчет ссылок для «удаления» данных.

Что ваша программа делает это следующим образом:

  1. Создание объекта и присвоить ссылку на $object1
  2. Понял ссылка на $object2 и увеличиваем счетчик ссылок объекта
  3. Изменить значение $object2 и уменьшает счетчик ссылок объекта.

В конце концов вы все еще удерживаете объект через $object1, и его количество ссылок не упадет ниже 1, пока вы его удерживаете. Технически, когда ваша программа отключается, переменная $object1 будет уничтожена, поскольку она выходит за пределы области действия, при которой счетчик ссылок объекта упадет до 0, и perl будет искать и попытаться вызвать его метод DESTROY.

Если вы действительно хотите «увидеть» уничтоженный предмет, вы можете изучить метод DESTROY, который выводит сообщение об уничтожении объекта. Таким образом, вы можете «отпустить» свою последнюю ссылку и по-прежнему видеть ее разрушение.

+0

Хорошо, это объясняет, что происходит, но как я могу заставить Perl одновременно устранить «$ object1» и «$ object2»? – tjwrona1992

+0

@ tjwrona1992 Действие на расстоянии обычно не считается желательным.но вместо * копирования * вашей ссылки, я полагаю, вы могли бы создать '$ object2' в качестве * псевдонима * для' $ object1'. – tjd

+0

Как вы можете это сделать? – tjwrona1992

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. 
+0

Это было бы здорово, если бы у этих объектов был только один атрибут, но они могут иметь много разных атрибутов, и некоторые из этих атрибутов могут оставаться действительными. Я знаю, что мой пример выше не учитывает это, поскольку я удаляю весь объект, но на самом деле у меня очень сложная структура данных, где только небольшие разделы могут стать недействительными, а если они недействительны, я бы хотел удалить их, чтобы они не могли быть доступ снова, без сбоев программы. Я только хочу, чтобы он потерпел крах, если пользователь явно пытается получить недопустимые данные. – tjwrona1992

+0

Совет. Если это помогает, 'delete' может записывать фрейм стека, чтобы включить его в сообщение об ошибке, появившееся при обращении к недопустимому объекту. – ikegami

+0

Это не проблема. Ваш конструктор атрибутов будет строить все атрибуты, чтобы проверить, действительно ли объект. – ikegami

Смежные вопросы