Технология объектно-ориентированного программирования представляет из себя современный подход к созданию
Но программистам, пишущим на
В нынешней версии
Теперь рассмотрим примеры описания
bless ("благословить"), благодаря которой каждый созданный объект помечается принадлежащим к определенному классу. После этого при обращении к методам объекта они отыскиваются в пакете с таким же именем. Вот как происходит превращение объекта "
my $class = 'Hobbit'; # имя класса в виде строки
my $object = { }; # ссылка на анонимный хэш,
# где будут храниться данные объекта,
bless($object, $class); # "благословляется" указывать
# на объект класса $class
Для примера опишем
package Person; # класс - это пакет
sub new { # метод-конструктор объектов
my $class = shift; # 1-й параметр ссылка на имя класса
my $self = {}; # контейнер для атрибутов объекта
$self->{name} = ''; # начальные значения атрибутов
bless($self, $class); # "благословить" объект ссылки
return $self; # вернуть ссылку на созданный объект
}
Затем в описании 'name' ("имя") и метод для изменения его значения (
sub say_name { # метод доступа (accessor) к атрибуту name
my ($self) = @_; # получить ссылку на объект
return $self->{name}; # вернуть значение атрибута
}
sub give_name { # метод изменения (modifier) атрибута name
my $self = $_[0]; # 1-й аргумент: ссылка на объект
$self->{name} = $_[1]; # 2-й аргумент: новое значение
}
1; # истинное значение требуется для use
__END__ # конец описания класса
В ' ("рост"):
sub height { # метод чтения и записи атрибута height
my $self = shift; # извлечь ссылку на объект
$self->{height} = shift # присвоить новое значение,
if @_; # если передан аргумент
return $self->{height}; # вернуть значение атрибута
}
Обратите внимание, что описание
В программе, в которой применяются объекты описанного
# способ обращения к методам через ссылки на объекты
use Person; # будем использовать этот класс
# создать объект класса,
my $hobbit = Person->new(); # вызвав его конструктор
# задать значение свойства, обратившись к методу объекта
$hobbit->give_name('Фродо Бэггинс');
# создать другой объект
my $dwarf = Person->new; # () не обязательны
$dwarf->give_name('Гимли'); # задать значение свойства
# запросить значения свойств, обратившись к методам
print $hobbit->say_name(), ' ', $dwarf->say_name, "\n";
Взаимодействие с объектом строится на обращении к его методам. Обращение к методу происходит при помощи
$hobbit->give_name('Бильбо Бэггинс'); # соответствует вызову:
Person::give_name($hobbit, 'Бильбо Бэггинс');
Внутри метода
Если к ссылке на объект ref(), то она вернет значение не ', как можно было бы предположить, а '! Это результат "благословения" объекта bless().
print "Класс объекта: '", ref($hobbit), "'\n"; # 'Person'
Кроме
# способ обращения к методам через косвенные объекты use Person; # используем класс Person my $magician = new Person; # "этот маг - новая личность" give_name $magician 'Гэндальф'; # "назовем мага 'Гэндальф'" my $name = say_name $magician; # "назови себя, маг" print $name, "\n";
В качестве иллюстрации к сказанному на рис. 14.1 изображены языковые конструкции, применяемые при работе с объектами, и их взаимосвязи.
(рис 14.1) Конструкции объектного программирования в Perl@ текущего @. Приведем пример описания :
package Wizard; # класс "Маг" our @ISA = qw(Person); # является подклассом Person use Person; # и использует пакет Person # ... описание методов класса Wizard... 1; # вернуть истину для use
Смысл наследования - в создании новый метод для работы со свойством 'magic' ("тип магии" - белая или черная):
sub magic { # магия - вот что отличает волшебника
my $self = shift; # извлечь ссылку на объект
$self->{magic} = shift if @_; # изменить значение
return $self->{magic}; # вернуть значение
}
Кроме того, переопределим new() так, чтобы он принимал два 'name' и 'magic'. Для создания объекта воспользуемся
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'
Естественно, что у объекта можно вызывать не только методы собственного .
В . undef($ или при окончании программы. Приведем пример шуточного деструктора для STDERR, называя say_name():
sub DESTROY {
warn('Прощайте, я ухожу... ' . shift->say_name);
}
bless(). Недостатком этого подхода можно считать то, что
$hobbit->{magic} = 'пёстрая'; # добавлен ошибочный атрибут
Для того чтобы надежно обеспечить . В новой версии
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;
package main; # вызывающая программа
use Private::Person; # использовать этот класс
my $elf = Private::Person->new; # создать объект и
$elf->name("Леголас"); # задать значения
$elf->height(189); # его атрибутам
# получить доступ к значениям атрибутов объекта
print $elf->name, ' ', $elf->height, ' ';
print ref($elf), "\n"; # тип референта: 'Private::Person'
Из примера видно, что
Обратите также внимание на то, что определен так, что он может вызываться с использованием либо имени
my $class = ref($invocant) || $invocant;
Если первым new() существующего объекта. Например, так:
my $hobbit = Private::Person->new; # вызов с именем класса
$hobbit->name("Bilbo Baggins");
my $frodo = $hobbit->new; # вызов со ссылкой на объект
$frodo->name("Frodo Baggins");
В Magic::, где метод будет использоваться для доступа к значению атрибута $Magic::, в котором будет храниться количество созданных волшебных колец.
package Magic::Ring; # класс "Магическое Кольцо"
sub new { # конструктор
my ($class, $owner) = @_; # имя класса и значение атрибута
$Magic::Ring::count++; # сосчитать новое Кольцо
bless({owner => $owner}, $class); # "благословить" хэш
}
sub owner { # метод чтения и записи атрибута owner
my $self = shift; # извлечь ссылку на объект
$self->{owner} = shift if @_; # изменить значение атрибута
return $self->{owner}; # вернуть значение атрибута
}
$Magic::Ring::count = 0; # атрибут класса: число Колец
sub count { # метод класса
return $Magic::Ring::count;
}
1; # конец описания класса Magic::Ring
В программе, использующей Magic::, создается набор объектов. При каждом обращении к $Magic::.
package main;
use Magic::Ring; # использовать класс "Магическое Кольцо"
my @rings = ();
for (1..3) { # "Три кольца - премудрым эльфам..."
push @rings, new Magic::Ring('эльф');
}
for (1..7) { # "Семь колец - пещерным гномам..."
push @rings, new Magic::Ring('гном');
}
for (1..9) { # "Девять - людям Средиземья..."
push @rings, new Magic::Ring('человек');
}
# "А Одно - всесильное - Властелину Мордора..."
push @rings, new Magic::Ring('Саурон');
# Сколько всего было сделано колец?
print Magic::Ring->count, "\n"; # будет выведено: 20
В , который облегчает жизнь программистам по описанию struct(). Эта функция генерирует описание
use Class::Struct; # подключаем стандартный модуль
# описываем класс Performer ("Исполнитель")
struct Performer => { # атрибуты класса:
name => '$', # "имя" - скаляр
country => '$', # "страна" - скаляр
artists => '%', # "артисты" - хэш
};
my $performer = new Performer; # создаем исполнителя
$performer->name('Pink Floyd'); # задаем значения атрибутов
$performer->country('Great Britain');
# заполняем атрибут-хэш:
$performer->artists('David Gilmour', 'гитары, вокал');
$performer->artists('Roger Waters', 'бас-гитара, вокал');
$performer->artists('Nick Mason', 'ударные');
$performer->artists('Richard Wright', 'клавишные');
# описываем класс Album ("Альбом")
struct Album => { # атрибуты класса:
title => '$', # "название" - скаляр
year => '$', # "год выхода" - скаляр
tracks => '@', # "композиции" - массив
performer => 'Performer', # "исполнитель" - объект
};
my $album = Album->new; # создаем альбом
$album->title('Dark Side of the Moon');
$album->year(1973);
# заполняем атрибут-массив:
$album->tracks(0, 'Breathe');
$album->tracks(1, 'Time');
# и так далее...
$album->performer($performer); # задаем атрибут-объект
Чтобы добавить к полученному описанию Album::print и его использования в главной программе:
package Album; # переключаемся на нужный пакет
sub Album::print { # и описываем дополнительный метод
my $self = shift;
printf("%s '%s' (%d)\n",
$self->performer->name, $self->title, $self->year);
foreach my $artist (keys%{$self->performer->artists}) {
printf("\t%s - %s\n",
$artist, $self->performer->artists($artist));
}
}
package main; # переключаемся на основную программу
$album->print; # и вызываем метод объекта
В заключение рассмотрим несколько распространенных приемов для работы с классами и объектами.
Функции bless() не обязательно передавать bless() возвращает значение своего первого
sub new { # конструктор экземпляров класса
my $self = {}; # контейнер для атрибутов объекта
bless($self); # "благословить" объект ссылки
} # и вернуть ссылку (1-й аргумент bless)
При создании объекта удобно сразу задавать начальные значения его атрибутов, передавая аргументы
my $language = Programming::Language->new( NAME => 'Perl', # имя VERSION => '5.8.7', # версия AUTHOR = 'Larry Wall' # автор );
Весьма полезно иметь в as_string() или to_string() и может применяться для отладочной печати состояния объекта. А если его определить в
sub to_string { # преобразование значений атрибутов в строку
my $self = shift;
my $string = '{ ';
foreach (keys %{$self}) {
$string .= "$_: '$self->{$_}' ";
}
$string .= '}';
return $string;
}
Благодаря тому, что
package Human; # класс "Человек"
our @ISA = qw(Person); # это подкласс класса Person
use Person;
sub set { # универсальный метод изменения атрибутов объекта
my ($self, $name, $new_value) = @_;
my $old_value = $self->{$name};
$self->{$name} = $new_value;
return $old_value;
}
sub get { # универсальный метод доступа к атрибутам объекта
my ($self, $name) = @_;
return $self->{$name};
}
1;
package main; # главная программа
use Human; # подключить класс
my $hero = Human->new; # создать героя-человека
$hero->set ('имя', 'Арагорн'); # дать ему имя
$hero->set ('оружие', 'меч'); # и вооружить
В этой лекции мы научились работать с объектами. Объектный подход реализован в
Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.