среда, 3 июня 2009 г.

Объекты на замыканиях - надежная защита

Perl не препятствует прямому обращению и управлению данными объектов. Просто существует договоренность, что так делать не хорошо. Если все-таки необходимо явно возвести препятствие прямому доступу, можно воспользоваться Inside-out объектами. Однако Inside-out содержат лазейку, которая позволяет заглянуть за кулисы объекта (смотрите "Закрытые объекты" в Perl5 и Perl6).

Полную закрытость данных объекта обеспечивает лишь замыкание.

Рассмотрим в качестве примера объект, конструктор которого принимает число, и который имеет два метода: too - возвращает инициализирующие число, baz - возвращает результат сложения с указным числом:

package Foo;

sub new {
shift;
my $foo = shift;
my $self = \$foo;
bless $self;
return $self;
}

sub too {
my $self = shift;
return $$self;
}

sub baz {
my $self = shift;
return $$self + shift;
}

package main;
my $foo = Foo->new(2);
print $foo->too(), "\n"; # 2
print $foo->baz(3), "\n"; # 5

Замыкание с аналогичным функционалом выглядит следующим образом:

sub new_foo {
my $foo = shift;
return sub {
my $method = shift;
if ($method eq "too") {
return $foo;
} elsif ($method eq "baz") {
return $foo + shift;
}
};
}

my $foo = new_foo(2);
print $foo->("too"), "\n"; # 2
print $foo->("baz", 3), "\n"; # 5

Вызов методов объекта-замыкания несколько необычен для тех, кто привык к объектам на основе классов. К счастью, Perl очень гибкий языки и позволяет устранить вышеупомянутое "неудобство", "посвятив" быть объектом непосредственно само замыкание:

package Foo;

sub new {
shift;
my $foo = shift;
my $self = sub {
my $method = shift;
if ($method eq "too") {
return $foo;
} elsif ($method eq "baz") {
return $foo + shift;
}
};
bless $self;
return $self;
}

foreach my $method (qw(too baz)){
no strict 'refs';
*$method = sub { my $self = shift; return $self->($method, @_) };
}

package main;
my $foo = Foo->new(2);
print $foo->too(), "\n"; # 2
print $foo->baz(3), "\n"; # 5

Как видим, все просто, единственно, что пришлось добавить, так это трансляцию методов доступа в вызовы замыкания. Но при этом, имея единственную точку входа, можно легко добавить различные проверки доступа к методам объекта.

Комментариев нет: