понедельник, 28 января 2008 г.

Объекты? Зачем?! Точнее, не всегда. Замыкания!

Заметка не предназначена для разжигания священной войны: хорошо или плохо объектно ориентированное программирование. Я сам использую его наравне с другими.

Цель заметки --- показать, что иногда проще обойтись без объектов, а использовать замыкания.

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

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

package Foo;

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

sub foo {
my $self = shift;
$$self += shift;
print $$self, "\n";
}

1;

Пример использования:

use Foo;
my $foo = Foo->new(3);
$foo->foo(1);
$foo->foo(1);
$foo->foo(2);
$foo->foo(2);

Теперь сделаем аналогичный по функционалу "сумматор" с использованием замыкания:

sub make_foo {
my $foo = shift;
return sub {
$foo += shift;
print $foo, "\n";
};
}

Пример использования:

my $foo = make_foo(3);
$foo->(1);
$foo->(1);
$foo->(2);
$foo->(2);

Как видим вариант с замыканием проще, компактней и элегантней.

Пожалуй на этом и остановимся --- читатель дальше сможет сам развить тему. Приведу лишь цитату Стива Маджевски: "Объект --- это совокупность данных вместе с привязанными к ним процедурами... Замыкание --- это процедура вместе с привязанной к ней совокупностью данных."


P.S.
Кстати, Parrot оперирует объектами (PMC),
но при вызовах подпрограмм использует стиль передачи продолжений, который не мыслим без замыканий.

P.P.S
Копия и комментарии находятся на kiev.pm.org