Вход/Регистрация
Язык программирования Perl
вернуться

Шохирев Михаил Васильевич

Шрифт:

sub new { # конструктор объектов

my $class = $_[0]; # имя класса в 1-м аргументе

my $self = new Person; # маг - это личность

$self->{name} = $_[1]; # задать имя из 2-го аргумента

$self->{magic} = $_[2]; # и тип магии из 3-го

bless($self, $class); # "благословить" мага

return $self; # вернуть ссылку на объект

}

Вызывающая программа, использующая производный класс, будет выглядеть следующим образом:

use Wizard; # подключить производный класс

# создать нового черного мага - Сарумана

my $wizard = new Wizard('Саруман', 'black');

my $name = say_name $wizard; # "назови себя, маг"

print $name, ' ', $wizard->magic; # 'Саруман black'

print ref($wizard); # тип объекта ссылки - 'Wizard'

Естественно, что у объекта класса Wizard можно вызывать не только методы собственного класса, но и любые методы, унаследованные из родительского класса Person.

В классе может быть описан специальный метод, автоматически вызываемый исполняющей системой при уничтожении каждого объекта. Такой метод называется деструктор (destructor), и он должен иметь зарезервированное имя - DESTROY. Деструктор вызывается при освобождении памяти, занимаемой объектом: это происходит при выходе из блока, где был создан объект, при удалении последней ссылки на объект функцией undef($object) или при окончании программы. Приведем пример шуточного деструктора для класса Person, который при удалении объекта направляет прощание в поток STDERR, называя имя объекта методом say_name:

sub DESTROY {

warn('Прощайте, я ухожу... ' . shift->say_name);

}

Деструктор может использоваться, если при окончании работы с объектом нужно выполнить какие-то завершающие действия: например, удалить динамически созданные структуры или сохранить данные объекта в файле. Конструктор в этом случае может считывать сохраненные значения из файла, чтобы присвоить объектам начальные значения.

Анонимные хэши - это самый распространенный, но не единственный способ хранить значения атрибутов объекта. Для этого может применяться массив или даже скалярная переменная, лишь бы при создании объекта в конструкторе это хранилище значений было связано с именем класса функцией bless. Недостатком этого подхода можно считать то, что ограничение доступа к свойствам достигается лишь на уровне соглашения пользоваться только методами объекта. И поскольку существует возможность изменить значение атрибута напрямую, это может нарушить корректную работу программы. Ведь в методе изменение состояния объекта сопровождается необходимыми проверками, чего не происходит при непосредственном изменении атрибута. Тем более, что в некоторых случаях атрибуты вообще должны быть доступны только для чтения (read-only attribute). Например, при использовании хэша для хранения атрибутов вполне возможно такое некорректное присваивание:

$hobbit->{magic} = 'пёстрая'; # добавлен ошибочный атрибут

Для того чтобы надежно обеспечить ограничение доступа к данным, которые хранятся в объекте, применяются замыкания. Чтобы показать, как можно организовать полностью закрытые атрибуты (private attributes) с помощью замыканий, напишем класс Private::Person. В новой версии класса значения атрибутов также хранятся в анонимном хэше, но при создании объекта возвращается ссылка не на него, а на анонимную подпрограмму доступа к данным. Этой функции будет передаваться имя атрибута (и, возможно, новое значение), а она будет возвращать значение атрибута, используя имя атрибута как ключ поиска в анонимном массиве. Это выглядит так:

package Private::Person; # класс "Личность"

sub new { # прототипом может быть

my $invocant = shift; # класс или объект

my $class = ref($invocant) || $invocant;

my $self = { # значения атрибутов:

NAME => '', # имя и

HEIGHT => 0.0 # рост

};

my $closure = sub { # функция доступа к данным

my $field = shift; # по имени атрибута

$self->{$field} = shift if @_; # изменим и

return $self->{$field}; # вернем значение

}; # объектом будет

bless($closure, $class); # ссылка на функцию

}

# метод доступа к атрибуту name

sub name {

my $self = shift; # ссылка на объект-функцию

&{$self}("NAME", @_); # доступ к скрытому значению

}

# метод доступа к атрибуту height

sub height { # то же, что выше, но несколько короче:

&{ $_[0] }("HEIGHT", @_[1 .. $#_ ] )

}

1;

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

  • Читать дальше
  • 1
  • ...
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: