Archive

Archive for July, 2007

Perl и фиксированные ключи в хеше.

July 5th, 2007 No comments

Некоторое время назад мне приходилось писать довольно большой проект на PHP. Тогда очень хотелось от хешей возможности зафиксировать множество ключей, чтобы не отлавливать по десяткам файлов опечатки в названиях полей сложных многоуровневых структур данных.

Тогда решения не нашлось. И сейчас PHP для меня лично уходит потихоньку в прошлое, т.к. в perl нахожу все больше интересных возможностей, которых раньше не хватало.
Так вот, по поводу фиксированного набора ключей, вот пример объекта на основе такого хеша:

package some;

use warnings;
use strict;
use Hash::Util qw{lock_keys};

sub new
{
my $class = shift;
my %hash;
my @keys = ("one", "two", "three", "four", "five");
my $self = bless \%hash, $class;
lock_keys %hash, @keys;
return $self;
}

1;

Теперь при выполнении инструкция $some->{‘there’} произойдет ошибка:
Attempt to access disallowed key 'there' in a restricted hash at ./test.pl line 11.

Причем сделано это не через Tie, чего я сначала опасался, а собственными средствами компилятора, т.е. должно работать очень быстро.

Но вообще-то, в каждой книге по ООП-прогрммированию обязателно замолвят слово о том, что открытые свойства класса это не очень хорошо, и что их значения предпочтительней изменять с помощью методов. А ведь их лень писать для каждой переменной!! Но хорошие языки тем и отличаются, что на них вовсе не сложно писать красиво и правильно. Смотрим, что предлагает Perl (пример из документации):


package Foo;
use base qw(Class::Accessor);
Foo->mk_accessors('foo'); # или mk_ro_accessors(qw{ one two three }) для read-only полей

my $obj = Class->new({ foo => 42 });
print $obj->foo; # 42
$obj->foo("24");
print $obj->foo; # 24

Ну вот и все! Теперь если захочется изменить поведение объекта таким образом, чтобы при изменении свойства foo, менялось также значение bar, достаточно реализовать самостоятельно нужную функцию, а править использующий класс код не нужно.

Все-таки perl язык великий и могучий, этого у него не отнять!