Це команда perlobj, яку можна запустити у безкоштовного хостинг-провайдера OnWorks за допомогою однієї з наших безкоштовних онлайн-робочих станцій, таких як Ubuntu Online, Fedora Online, онлайн-емулятор Windows або онлайн-емулятор MAC OS
ПРОГРАМА:
ІМ'Я
perlobj - посилання на об'єкт Perl
ОПИС
У цьому документі міститься довідка щодо можливостей об’єктної орієнтації Perl. Якщо ви
шукаєте введення в об’єктно-орієнтоване програмування на Perl, перегляньте perlootut.
Щоб зрозуміти об’єкти Perl, вам спочатку потрібно зрозуміти посилання в Perl. Побачити
perlref для деталей.
Цей документ описує всі об’єктно-орієнтовані (ОО) функції Perl з самого початку. Якщо
ви просто хочете написати якийсь власний об’єктно-орієнтований код, ймовірно
краще обслуговувати за допомогою однієї з систем об’єктів із CPAN, описаних у perlootut.
Якщо ви хочете написати власну систему об’єктів або вам потрібно підтримувати код, який
реалізує об’єкти з нуля, тоді цей документ допоможе вам зрозуміти, як саме
Perl виконує об'єктну орієнтацію.
Є кілька основних принципів, які визначають об'єктно-орієнтований Perl:
1. Об’єкт — це просто структура даних, яка знає, до якого класу вона належить.
2. Клас – це просто пакет. Клас надає методи, над якими очікується дія
об’єкти.
3. Метод — це просто підпрограма, яка очікує посилання на об’єкт (або пакет
ім'я, для методів класу) як перший аргумент.
Давайте детально розглянемо кожен із цих принципів.
An Об'єкт is просто a дані структура
На відміну від багатьох інших мов, які підтримують об'єктну орієнтацію, Perl її не підтримує
спеціальний синтаксис для побудови об'єкта. Об'єкти - це просто структури даних Perl
(хеші, масиви, скаляри, дескриптори файлів тощо), які були явно пов’язані з
певний клас.
Ця явна асоціація створюється вбудованою функцією "благословення", яка зазвичай є
використовується в межах конструктор підпрограма класу.
Ось простий конструктор:
файл пакета;
під новий {
мій $class = shift;
повернути благословення {}, $клас;
}
Назва «новий» не є особливою. Ми могли б назвати наш конструктор інакше:
файл пакета;
підзавантаження {
мій $class = shift;
повернути благословення {}, $клас;
}
Сучасна конвенція для модулів OO полягає в тому, щоб завжди використовувати "новий" як назву для
конструктор, але це не вимагається. Будь-яка підпрограма, яка благословляє дані
структуру в клас є дійсним конструктором у Perl.
У попередніх прикладах код "{}" створює посилання на порожній анонімний хеш.
Потім функція "благословення" бере це посилання та пов’язує хеш із класом у
$клас. У найпростішому випадку змінна $class буде містити рядок
"Файл".
Ми також можемо використовувати змінну для зберігання посилання на структуру даних, яка створюється
благословенний як наш об'єкт:
під новий {
мій $class = shift;
мій $self = {};
благословити $self, $class;
повернути $self;
}
Після того, як ми благословили хеш, на який посилається $self, ми можемо почати викликати його методи. Це
корисно, якщо ви хочете розмістити ініціалізацію об’єкта в окремому методі:
під новий {
мій $class = shift;
мій $self = {};
благословити $self, $class;
$self->_initialize();
повернути $self;
}
Оскільки об’єкт також є хешем, ви можете розглядати його як один, використовуючи для зберігання даних
пов'язані з об'єктом. Як правило, код всередині класу може трактувати хеш як
доступну структуру даних, тоді як код поза класом завжди повинен розглядати об’єкт як
непрозорий. Це називається герметизація. Інкапсуляція означає, що це робить користувач об’єкта
не потрібно знати, як це реалізовано. Користувач просто викликає документовані методи на
об'єкт
Зауважте, однак, що (на відміну від більшості інших мов орієнтованого орієнтування) Perl не гарантує та не примусово дотримується
інкапсуляція будь-яким способом. Якщо ви хочете, щоб об’єкти насправді be непрозорий вам потрібно організувати
за це себе. Це можна зробити різними способами, зокрема за допомогою «Навиворіт
об’єкти» або модулі з CPAN.
Об'єкти Є блаженний; Змінні Є Чи не
Коли ми щось благословляємо, ми не благословляємо змінну, яка містить посилання на
це, а також ми не благословляємо посилання, яке зберігає змінна; ми благословляємо
річ, на яку посилається змінна (іноді відома як референт). Це найкраще
продемонстровано за допомогою цього коду:
використовуйте Scalar::Util 'благословенний';
мій $foo = {};
мій $bar = $foo;
благословити $foo, 'Клас';
print blessed( $bar ) // 'not blessed'; # друкує "Клас"
$bar = "якесь інше значення";
print blessed( $bar ) // 'not blessed'; # відбитки "не благословенний"
Коли ми називаємо "благословення" для змінної, ми фактично благословляємо базову структуру даних
на яку посилається змінна. Ми не благословляємо ні посилання, ні змінну
який містить це посилання. Ось чому другий виклик "благословенний( $bar)" повертається
помилковий. У цей момент $bar більше не зберігає посилання на об’єкт.
Іноді ви побачите, що в старих книгах або документації згадується «благословення посилання» або
описати об'єкт як "благословенний посилання", але це неправильно. Це не довідка
що благословляється як предмет; це річ, на яку посилається посилання (тобто референт).
A Клас is просто a пакет
Perl не надає спеціального синтаксису для визначень класів. Пакет – це просто a
простір імен, що містить змінні та підпрограми. Єдина відмінність полягає в тому, що в класі,
підпрограми можуть очікувати посилання на об'єкт або ім'я класу як перше
аргумент. Це суто питання умовності, тому клас може містити як методи, так і
підпрограми, які НЕ оперувати об'єктом або класом.
Кожен пакет містить спеціальний масив під назвою @ISA. Масив @ISA містить список цього
батьківські класи класу, якщо такі є. Цей масив перевіряється, коли Perl виконує вирішення методів,
які ми розглянемо пізніше.
Можна вручну встановити @ISA, і ви можете побачити це в старішому коді Perl. Набагато старше
код також використовує базову прагму. Для нового коду ми рекомендуємо використовувати батьківську прагму
оголосити своїх батьків. Ця прагма подбає про налаштування @ISA. Він також завантажиться
батьківські класи та переконайтеся, що пакет не успадковує сам себе.
Незважаючи на те, що батьківські класи встановлено, змінна @ISA пакета міститиме список
ті батьки. Це просто список скалярів, кожен з яких є рядком, який
відповідає назві пакета.
Усі класи успадковують від класу UNIVERSAL неявно. Клас УНІВЕРСАЛЬНИЙ є
реалізований ядром Perl і надає кілька методів за замовчуванням, таких як "isa()",
"can()" і "VERSION()". Клас «УНІВЕРСАЛЬНИЙ» буде ніколи відображаються в пакеті @ISA
змінна.
Perl тільки забезпечує успадкування методів як вбудовану функцію. Спадкування атрибутів є
залишений клас для реалізації. Докладні відомості див. у розділі «Засоби доступу до запису».
A Метод is просто a Підпрограма
Perl не надає спеціального синтаксису для визначення методу. Метод — це просто a
звичайна підпрограма, яка оголошується за допомогою "sub". Що робить метод особливим, так це те, що він
очікує отримати або об'єкт, або ім'я класу як свій перший аргумент.
Perl робить забезпечити спеціальний синтаксис для виклику методу, оператор "->". Ми будемо покривати
про це більш детально пізніше.
Більшість методів, які ви пишете, будуть працювати з об’єктами:
sub save {
my $self = зміна;
відкрити мій $fh, '>', $self->path() або померти $!;
вивести {$fh} $self->data() або померти $!;
закрити $fh або померти $!;
}
Метод благання
Виклик методу об’єкта записується як «$object->method».
Ліва сторона оператора виклику методу (або стрілки) є об’єктом (або класом
ім’я), а праворуч – ім’я методу.
my $pod = File->new( 'perlobj.pod', $data );
$pod->зберегти();
Синтаксис "->" також використовується під час розіменування посилання. Виглядає так само
але це дві різні операції.
Коли ви викликаєте метод, елемент зліва від стрілки передається як перший
аргумент для методу. Це означає, що коли ми викликаємо "Critter->new()", метод "new()".
отримує рядок "Critter" як перший аргумент. Коли ми викликаємо "$fred->speak()",
Змінна $fred передається як перший аргумент у "speak()".
Як і в будь-якій підпрограмі Perl, усі аргументи, передані в @_, є псевдонімами для
оригінальний аргумент. Це включає сам об'єкт. Якщо ви призначаєте безпосередньо $_[0] вас
змінить вміст змінної, яка містить посилання на об’єкт. ми
рекомендую не робити цього, якщо ви точно не знаєте, що робите.
Perl дізнається, у якому пакеті знаходиться метод, дивлячись на ліву сторону стрілки. Якщо
Ліва сторона – це ім’я пакета, він шукає метод у цьому пакеті. Якщо зліва
сторона hand є об’єктом, тоді Perl шукає метод у пакеті, який містить об’єкт
був благословенний в.
Якщо в лівій частині немає ані назви пакета, ані об’єкта, тоді буде виклик методу
викликати помилку, але дивіться розділ «Варіанти виклику методу» для отримання додаткових нюансів.
Спадкування
Ми вже говорили про спеціальний масив @ISA і батьківську прагму.
Коли клас успадковує від іншого класу, будь-які методи, визначені в батьківському класі, є
доступні для дитини класу. Якщо ви намагаєтесь викликати метод для об’єкта, який не є
визначений у власному класі, Perl також шукатиме цей метод у будь-якому батьківському класі, який він може
є.
пакет File::MP3;
використовувати батьківський 'Файл'; # встановлює @File::MP3::ISA = ('Файл');
my $mp3 = File::MP3->new( 'Andvari.mp3', $data );
$mp3->зберегти();
Оскільки ми не визначили метод "save()" у класі "File::MP3", Perl розгляне
Батьківські класи класу "File::MP3", щоб знайти метод "save()". Якщо Perl не може знайти a
метод "save()" будь-де в ієрархії успадкування, він помре.
У цьому випадку він знаходить метод "save()" у класі "Файл". Відзначимо, що об'єкт пройшов
to "save()" у цьому випадку все ще є об'єктом "File::MP3", навіть якщо метод знайдено в
клас «Файл».
Ми можемо перевизначити батьківський метод у дочірньому класі. Коли ми це зробимо, ми все одно зможемо викликати
метод батьківського класу з псевдокласом "SUPER".
sub save {
my $self = зміна;
скажіть «Приготуйтеся до розгойдування»;
$self->SUPER::save();
}
Модифікатор «СУПЕР» може тільки використовувати для викликів методів. Ви не можете використовувати його регулярно
виклики підпрограм або методи класу:
SUPER::save($thing); # FAIL: шукає save() sub у пакеті SUPER
SUPER->зберегти ($thing); # FAIL: шукає метод save() у класі
#СУПЕР
$thing->SUPER::save(); # Гаразд: шукає метод save() у батьківському
# класи
Як СУПЕР is Врегульований
Псевдоклас "SUPER" вирішується з пакета, у якому здійснюється виклик. Це є НЕ
вирішується на основі класу об’єкта. Це важливо, оскільки дозволяє використовувати методи
різні рівні в глибокій ієрархії успадкування правильно називають свій відповідний
батьківські методи.
пакет А;
під новий {
return bless {}, shift;
}
sub speak {
my $self = зміна;
сказати «А»;
}
пакет Б;
використовувати батьківський -norequire, 'A';
sub speak {
my $self = зміна;
$self->SUPER::speak();
сказати «Б»;
}
пакет С;
використовувати батьківський -norequire, 'B';
sub speak {
my $self = зміна;
$self->SUPER::speak();
сказати «С»;
}
мій $c = C->новий();
$c->говорити();
У цьому прикладі ми отримаємо такий результат:
A
B
C
Це демонструє, як вирішується "SUPER". Незважаючи на те, що об’єкт позначено літерою «C»
метод «speak()» у класі «B» все ще може викликати «SUPER::speak()» і очікувати його
щоб правильно шукати в батьківському класі "B" (тобто в класі, в якому знаходиться виклик методу), а не в
батьківський клас "C" (тобто клас, до якого належить об'єкт).
Бувають рідкісні випадки, коли це рішення на основі пакетів може бути проблемою. Якщо ви копіюєте a
підпрограми з одного пакета в інший, "SUPER" дозвіл буде виконано на основі
оригінальна упаковка.
множинний Спадкування
Множинне успадкування часто вказує на проблему дизайну, але Perl завжди дає достатньо
мотузка, на якій можна повіситися, якщо попросиш.
Щоб оголосити кількох батьків, вам просто потрібно передати кілька імен класів у «використовувати батьків»:
пакет MultiChild;
використовувати батьківський 'Parent1', 'Parent2';
Метод дозвіл замовлення
Порядок вирішення методів має значення лише у випадку множинного успадкування. У випадку
єдине успадкування, Perl просто шукає ланцюжок успадкування, щоб знайти метод:
Дідусь і дідусь
|
Parent
|
Дитина
Якщо ми викликаємо метод на об’єкті «Child», і цей метод не визначено в «Child»
Perl шукатиме цей метод у класі "Parent", а потім, якщо необхідно, у
Клас «Дідусь і бабуся».
Якщо Perl не зможе знайти метод у жодному з цих класів, він помре з повідомленням про помилку.
Коли клас має кілька батьків, порядок пошуку методів стає складнішим.
За замовчуванням Perl виконує пошук методу в глибину зліва направо. Це означає
починається з першого батьківського елемента в масиві @ISA, а потім шукає всіх батьківських елементів,
бабусь і дідусів тощо. Якщо не вдається знайти метод, він переходить до наступного батька в
масив @ISA вихідного класу та пошук звідти.
SharedGreatGrandParent
/\
Дідусь по батьковій лінії
\ /
Батько мати
\ /
Дитина
Отже, враховуючи наведену вище схему, Perl шукатиме «Дитина», «Батько», «Дідусь і дідусь»,
«Спільний прапрабатько», «мати» і, нарешті, «дідусь по материнській лінії». Це може бути a
проблема, оскільки зараз ми шукаємо "SharedGreatGrandParent" перед тим ми все це перевірили
похідні класи (тобто до того, як ми спробували "Mother" і "MaternalGrandparent").
За допомогою прагми mro можна запитати інший порядок вирішення методів.
пакет Дитячий;
використовувати mro 'c3';
використовуйте батьківський елемент 'Батько', 'Мати';
Ця прагма дозволяє перейти до порядку вирішення "C3". Простіше кажучи, порядок "C3".
гарантує, що спільні батьківські класи ніколи не шукаються перед дочірніми класами, тому Perl це зробить
тепер шукайте: «Дитина», «Батько», «Дідусь і бабуся по батькові», «Мати», «Дідусь і бабуся по матері» та
нарешті "SharedGreatGrandParent". Зауважте, однак, що це не пошук "вшир":
Усі «батькові» предки (крім загального предка) шукаються перед будь-яким із
«Материнськими» вважаються предки.
Порядок C3 також дозволяє викликати методи в однорідних класах з «наступним» псевдокласом.
Перегляньте документацію mro, щоб отримати докладнішу інформацію про цю функцію.
Метод дозвіл кешування
Коли Perl шукає метод, він кешує пошук, щоб майбутні виклики методу
не потрібно шукати його знову. Зміна батьківського класу класу або додавання підпрограм
до класу скасує кеш для цього класу.
Прагма mro надає деякі функції для безпосереднього керування кешем методів.
писемність Конструктори
Як ми згадували раніше, Perl не надає спеціального синтаксису конструктора. Це означає, що a
клас повинен реалізувати свій власний конструктор. Конструктор - це просто метод класу, який
повертає посилання на новий об'єкт.
Конструктор також може приймати додаткові параметри, які визначають об'єкт. Давайте напишемо
справжній конструктор для класу "Файл", який ми використовували раніше:
файл пакета;
під новий {
мій $class = shift;
my ( $path, $data ) = @_;
my $self = bless {
шлях => $шлях,
дані => $дані,
}, $клас;
повернути $self;
}
Як бачите, ми зберегли шлях і дані файлу в самому об’єкті. Пам'ятайте, під
капот, цей об'єкт все ще просто хеш. Пізніше ми напишемо засоби доступу для маніпулювання
ці дані.
Для нашого класу File::MP3 ми можемо перевірити, чи закінчується наданий нам шлях
".mp3":
пакет File::MP3;
під новий {
мій $class = shift;
my ( $path, $data ) = @_;
die "Ви не можете створити File::MP3 без розширення mp3\n"
якщо $path =~ /\.mp3\z/;
return $class->SUPER::new(@_);
}
Цей конструктор дозволяє своєму батьківському класу виконувати фактичне будівництво об’єкта.
Attributes
Атрибут — це частина даних, що належить певному об’єкту. На відміну від більшості об'єктів-
Орієнтовані мови, Perl не надає спеціального синтаксису або підтримки для оголошення і
маніпулювання атрибутами.
Атрибути часто зберігаються в самому об'єкті. Наприклад, якщо об’єкт є an
анонімний хеш, ми можемо зберігати значення атрибутів у хеші, використовуючи назву атрибута як
ключ.
Хоча можна безпосередньо посилатися на ці хеш-ключі поза класом, це
вважається найкращою практикою обернути весь доступ до атрибута методами доступу.
Це має кілька переваг. Аксесури полегшують зміну реалізації an
пізніше, зберігаючи оригінальний API.
Аксесор дозволяє додавати додатковий код навколо доступу до атрибутів. Наприклад, ви могли б
застосувати значення за замовчуванням до атрибута, який не було встановлено в конструкторі, або ви можете перевірити
що нове значення для атрибута є прийнятним.
Нарешті, використання засобів доступу значно спрощує успадкування. Підкласи можуть використовувати засоби доступу
замість того, щоб знати, як батьківський клас реалізований внутрішньо.
писемність Аксесуари
Як і у випадку з конструкторами, Perl не надає спеціального синтаксису оголошення доступу, тому класи
має надавати явно написані методи доступу. Є два поширених типи
засоби доступу, лише для читання та для читання-запису.
Простий засіб доступу лише для читання просто отримує значення одного атрибута:
підшлях {
my $self = зміна;
return $self->{path};
}
Аксесор читання-запису дозволить абоненту встановити значення, а також отримати його:
підшлях {
my $self = зміна;
якщо (@_) {
$self->{path} = shift;
}
return $self->{path};
}
An У бік МЕНЮ Розумніший та Безпечніше код
Наш конструктор і аксесуари не дуже розумні. Вони не перевіряють, чи є $path
визначено, а також не перевіряють, що $path є дійсним шляхом до файлової системи.
Виконання цих перевірок вручну може швидко стати втомливим. Написання купи аксесуарів за допомогою
рука також неймовірно стомлююча. У CPAN є багато модулів, які можуть вам допомогти
пишіть безпечніший і більш стислий код, включаючи модулі, які ми рекомендуємо в perlootut.
Метод виклик Варіації
Perl підтримує кілька інших способів виклику методів, крім використання "$object->method()"
ми бачили досі.
Метод імен as Рядки
Perl дозволяє використовувати скалярну змінну, яка містить рядок як назву методу:
my $file = File->new( $path, $data );
мій $method = 'зберегти';
$file->$method();
Це працює так само, як виклик "$file->save()". Це може бути дуже корисним для письма
динамічний код. Наприклад, це дозволяє передавати ім’я методу, яке буде викликано як параметр
до іншого методу.
Клас імен as Рядки
Perl також дозволяє використовувати скаляр, що містить рядок, як назву класу:
мій $клас = 'Файл';
мій $файл = $клас->новий($шлях, $дані);
Знову ж таки, це дозволяє створити дуже динамічний код.
Підпрограма посилання as Методи
Ви також можете використовувати посилання на підпрограму як метод:
мій $sub = sub {
my $self = зміна;
$self->save();
};
$file->$sub();
Це точно еквівалентно написанню "$sub->($file)". Ви можете побачити цю ідіому в дикій природі
у поєднанні з викликом "можна":
if ( my $meth = $object->can('foo') ) {
$object->$meth();
}
Повага Метод виклик
Perl також дозволяє використовувати розіменовані скалярні посилання у виклику методу. Це а
ковток, тому давайте подивимося на код:
$file->${ \'save' };
$file->${ returns_scalar_ref() };
$file->${ \( returns_scalar() ) };
$file->${ returns_ref_to_sub_ref() };
Це працює, якщо розіменування створює рядок or посилання на підпрограму.
Метод Виклики on Дескриптори файлів
Під капотом дескриптори файлів Perl є екземплярами класу "IO::Handle" або "IO::File".
Коли у вас є відкритий дескриптор файлу, ви можете викликати його методи. Додатково можна дзвонити
методи для дескрипторів файлів "STDIN", "STDOUT" і "STDERR".
відкрити мій $fh, '>', 'шлях/до/файлу';
$fh->autoflush();
$fh->print('вміст');
STDOUT->autoflush();
Викликаючи Клас Методи
Оскільки Perl дозволяє вам використовувати голі слова для імен пакетів і підпрограм, це
іноді неправильно тлумачить значення простого слова. Наприклад, конструкт
«Class->new()» можна інтерпретувати як «'Class'->new()» або «Class()->new()». в
Англійською ця друга інтерпретація звучить як «виклик підпрограми з іменем Клас(), а потім зателефонуйте
новий() як метод для значення, що повертається Клас()". Якщо є підпрограма з назвою
"Class()" у поточному просторі імен, Perl завжди інтерпретуватиме "Class->new()" як
друга альтернатива: виклик "new()" для об'єкта, повернутого викликом "Class()"
Ви можете змусити Perl використовувати першу інтерпретацію (тобто як виклик методу класу
під назвою «Клас») двома способами. По-перше, ви можете додати «::» до імені класу:
Class::->new()
Perl завжди інтерпретуватиме це як виклик методу.
Крім того, ви можете взяти назву класу в лапки:
'Клас'->новий()
Звичайно, якщо ім’я класу є скалярним, Perl також вчинить правильно:
my $class = 'Клас';
$клас->новий();
непрямий Об'єкт синтаксис
зовні of файл обробляти випадок, використання of це синтаксис is збентежений as it може збентежений
Perl перекладач. Читати нижче та цінності більше подробиці
Perl підтримує інший синтаксис виклику методу, який називається нотацією "непрямий об'єкт". Це
синтаксис називається "непрямим", тому що метод стоїть перед об'єктом, який він викликається
далі.
Цей синтаксис можна використовувати з будь-яким методом класу або об’єкта:
мій $файл = новий файл $шлях, $дані;
зберегти $file;
Ми рекомендуємо вам уникати цього синтаксису з кількох причин.
По-перше, це може заплутати читання. У наведеному вище прикладі незрозуміло, чи є «зберегти» a
метод, наданий класом "Файл" або просто підпрограмою, яка очікує файловий об'єкт як
його перший аргумент.
При використанні з методами класу проблема стає ще гіршою. Оскільки Perl допускає підпрограму
імена, які будуть записані у вигляді голих слів, Perl має вгадати, чи є голе слово після методу
це ім'я класу або ім'я підпрограми. Іншими словами, Perl може розпізнати синтаксис як будь-який
"Файл->новий($path, $data)" or "новий(Файл($path, $data))".
Щоб проаналізувати цей код, Perl використовує евристику на основі того, які назви пакетів він бачив, що
підпрограми існують у поточному пакеті, які голі слова він бачив раніше та інше
введення. Зайве говорити, що евристика може дати дуже дивовижні результати!
Старіша документація (і деякі модулі CPAN) заохочувала цей синтаксис, зокрема для
конструктори, тому ви все ще можете знайти його в дикій природі. Однак ми радимо вам уникати
використовувати його в новому коді.
Ви можете змусити Perl інтерпретувати голе слово як назву класу, додавши до нього "::", наприклад
ми бачили раніше:
мій $файл = новий файл:: $шлях, $дані;
"благословити", "благословенний", та "ref"
Як ми бачили раніше, об’єкт — це просто структура даних, яка була благословенна в клас
за допомогою функції «благословення». Функція "благословення" може приймати один або два аргументи:
my $object = bless {}, $class;
my $object = bless {};
У першій формі анонімний хеш передається в клас у $class. В
друга форма, анонімний хеш благословляється в поточний пакет.
Друга форма настійно не рекомендується, оскільки вона порушує здатність підкласу
повторно використовувати батьківський конструктор, але ви все одно можете зустріти його в існуючому коді.
Якщо ви хочете дізнатися, чи певний скаляр посилається на об’єкт, ви можете використовувати
"благословенна" функція, експортована Scalar::Util, яка постачається з ядром Perl.
використовуйте Scalar::Util 'благословенний';
if (визначено blessed($thing) ) { ... }
Якщо $thing посилається на об’єкт, то ця функція повертає ім’я пакета the
об'єкт був освячений в. Якщо $thing не містить посилання на благословенний об’єкт,
функція "blessed" повертає "undef".
Зверніть увагу, що "blessed($thing)" також поверне false, якщо $thing було благословлено в класі
з назвою «0». Це можливо, але цілком патологічно. Не створюйте клас з назвою "0"
якщо ти не знаєш, що робиш.
Подібним чином вбудована функція Perl "ref" обробляє посилання на благословенний об'єкт
спеціально. Якщо ви викликаєте "ref($thing)" і $thing містить посилання на об'єкт, це буде
повертає ім'я класу, в який був освячений об'єкт.
Якщо ви просто хочете перевірити, чи змінна містить посилання на об’єкт, ми рекомендуємо
що ви використовуєте "defined blessed($object)", оскільки "ref" повертає справжні значення для всіх
посилання, а не лише об’єкти.
Команда УНІВЕРСАЛЬНИЙ Клас
Усі класи автоматично успадковуються від класу UNIVERSAL, вбудованого в Perl
ядро. Цей клас надає ряд методів, усі з яких можна викликати або на a
клас або об'єкт. Ви також можете змінити деякі з цих методів у своєму класі.
Якщо ви це зробите, ми рекомендуємо вам дотримуватися вбудованої семантики, описаної нижче.
isa($клас)
Метод "isa" повертається правда якщо об’єкт є членом класу в $class, або a
член підкласу $class.
Якщо ви перевизначите цей метод, він ніколи не повинен викликати виключення.
DOES($role)
Метод "DOES" повертає правда якщо його об’єкт претендує на виконання ролі $role. за
за замовчуванням це еквівалентно "isa". Цей метод надається для використання системою об’єктів
розширення, які реалізують ролі, наприклад "Moose" і "Role::Tiny".
Ви також можете перевизначити "DOES" безпосередньо у своїх класах. Якщо ви перевизначите це
метод, він ніколи не повинен створювати виключення.
може ($ метод)
Метод «can» перевіряє, чи має клас або об’єкт, до якого він був викликаний, метод
під назвою $метод. Це перевіряє метод у класі та всіх його батьків. Якщо
метод існує, тоді повертається посилання на підпрограму. Якщо ні тоді
повертається "undef".
Якщо ваш клас відповідає на виклики методів через "AUTOLOAD", ви можете перевантажити "can"
щоб повернути посилання на підпрограму для методів, які обробляє ваш метод "AUTOLOAD".
Якщо ви перевизначите цей метод, він ніколи не повинен викликати виключення.
ВЕРСІЯ (потрібно $)
Метод "VERSION" повертає номер версії класу (пакета).
Якщо вказано аргумент $need, він перевірить, чи поточна версія (як визначено
за змінною $VERSION у пакеті) більше або дорівнює $need; це буде
померти, якщо це не так. Цей метод автоматично викликається формою «VERSION».
«користування».
використовуйте пакет 1.2 qw (деякі імпортовані субтитри);
# означає:
Пакет->ВЕРСІЯ(1.2);
Ми рекомендуємо вам використовувати цей метод для доступу до версії іншого пакета, а не
переглядаючи безпосередньо $Package::VERSION. Пакунок, який ви розглядаєте, міг мати
перевизначив метод "VERSION".
Ми також рекомендуємо використовувати цей метод, щоб перевірити, чи має модуль достатній рівень
версія. Внутрішня реалізація використовує модуль версії, щоб переконатися в цьому
різні типи номерів версій порівнюються правильно.
АВТОЗАвантаження
Якщо ви викликаєте метод, який не існує в класі, Perl видасть помилку. Проте, якщо
цей клас або будь-який з його батьківських класів визначає метод "AUTOLOAD", що "AUTOLOAD"
замість цього викликається метод.
"AUTOLOAD" викликається як звичайний метод, і абонент не буде знати різниці.
Будь-яке значення, яке повертає ваш метод "AUTOLOAD", повертається до абонента.
Повне ім’я викликаного методу доступне в пакеті $AUTOLOAD
глобальний для вашого класу. Оскільки це глобальне, якщо ви хочете посилатися, робіть це без a
префікс назви пакета під "строгим 'vars'", його потрібно оголосити.
# XXX - це жахливий спосіб реалізації інструментів доступу, але він працює
# для простого прикладу.
наш $AUTOLOAD;
sub AUTOLOAD {
my $self = зміна;
# Видалити кваліфікатор з оригінальної назви методу...
my $ called = $AUTOLOAD =~ s/.*:://r;
# Чи є атрибут із такою назвою?
die "Немає такого атрибута: $ called"
якщо не існує $self->{$ called};
# Якщо так, поверніть його...
return $self->{$ called};
}
sub DESTROY { } # див. нижче
Без оголошення "our $AUTOLOAD" цей код не компілюватиметься під strict
прагма.
Як сказано в коментарі, це не дуже хороший спосіб реалізації засобів доступу. Це теж повільно
розумний далеко. Однак ви можете розглядати це як спосіб надання засобів доступу в старішому коді Perl.
Перегляньте perlootut для отримання рекомендацій щодо ООП-кодування в Perl.
Якщо у вашому класі є метод "АВТОЗАВАНТАЖЕННЯ", ми наполегливо рекомендуємо замінити його
«можу» і у вашому класі. Ваш перевизначений метод "can" має повертати підпрограму
посилання для будь-якого методу, на який відповідає ваше "АВТОЗАВАНТАЖЕННЯ".
Деструктори
Коли останнє посилання на об’єкт зникає, об’єкт знищується. Якщо у вас тільки є
одне посилання на об’єкт, що зберігається в лексичному скалярі, при цьому об’єкт знищується
скаляр виходить за межі області видимості. Якщо ви зберігаєте об’єкт у глобальному пакеті, цей об’єкт може не зберігатися
виходити з області видимості, поки програма не завершить роботу.
Якщо ви хочете щось зробити, коли об’єкт знищено, ви можете визначити «DESTROY»
метод у вашому класі. Perl завжди викликає цей метод у відповідний час,
якщо метод не порожній.
Цей метод викликається так само, як і будь-який інший метод, з об’єктом як першим аргументом. Це робить
не отримати жодних додаткових аргументів. Однак змінна $_[0] буде лише для читання в
деструктор, тому ви не можете призначити йому значення.
Якщо ваш метод "DESTROY" видає помилку, ця помилка буде проігнорована. Його не відправлять
на "STDERR", і це не спричинить загибель програми. Однак, якщо ваш деструктор є
виконується всередині блоку "eval {}", тоді помилка змінить значення $@.
Оскільки методи "DESTROY" можна викликати будь-коли, вам слід локалізувати будь-який глобал
змінні, які ви можете оновити у своєму "DESTROY". Зокрема, якщо ви використовуєте "eval {}", ви
має локалізувати $@, а якщо ви використовуєте «систему» або зворотні галочки, вам слід локалізувати $?.
Якщо ви визначите "АВТОЗАВАНТАЖЕННЯ" у своєму класі, тоді Perl викличе "АВТОЗАВАНТАЖЕННЯ" для обробки
метод «ЗНИЩИТИ». Ви можете запобігти цьому, визначивши порожнє «DESTROY», як ми робили в
приклад автозавантаження. Ви також можете перевірити значення $AUTOLOAD і повернутися без нього
робити що-небудь, коли викликають обробку "DESTROY".
Глобальний Знищення
Порядок, у якому об'єкти знищуються під час глобального знищення перед програмою
виходи непередбачувані. Це означає, що будь-які об’єкти, які містяться у вашому об’єкті, вже можуть
були знищені. Ви повинні перевірити, що об’єкт, що міститься, визначено перед викликом a
метод на ньому:
sub DESTROY {
my $self = зміна;
$self->{handle}->close() якщо $self->{handle};
}
Ви можете використовувати змінну "${^GLOBAL_PHASE}", щоб визначити, чи перебуваєте ви зараз у глобальній
фаза руйнування:
sub DESTROY {
my $self = зміна;
повернути, якщо ${^GLOBAL_PHASE} eq 'DESTRUCT';
$self->{handle}->close();
}
Зверніть увагу, що ця змінна була додана в Perl 5.14.0. Якщо ви хочете виявити глобальне
етап знищення на старих версіях Perl, ви можете використовувати "Devel::GlobalDestruction"
модуль на CPAN.
Якщо ваш метод "DESTROY" видає попередження під час глобального знищення, інтерпретатор Perl
до попередження додасть рядок «під час глобального знищення».
Під час глобального знищення Perl завжди збиратиме сміття об’єкти перед неблагословенним
посилання. Перегляньте "PERL_DESTRUCT_LEVEL" у perlhacktips для отримання додаткової інформації про глобальні
руйнування.
Нехешований Об'єкти
Усі приклади досі демонстрували об’єкти, засновані на благословенному хеші. Однак це
можна благословити будь-який тип структури даних або референт, включаючи скаляри, глобуси та
підпрограми. Ви можете побачити подібні речі, дивлячись на код у дикій природі.
Ось приклад модуля як благословенного скаляра:
час упаковки;
використовувати суворий;
використовувати попередження;
під новий {
мій $class = shift;
мій $time = час;
повернути благословити \$час, $клас;
}
підепоха {
my $self = зміна;
return ${ $self };
}
my $time = Time->new();
надрукувати $time->epoch();
вивернутий назовні об'єкти
У минулому спільнота Perl експериментувала з технікою під назвою «об’єкти навиворіт».
Об’єкт «навиворіт» зберігає свої дані поза посиланням на об’єкт, індексованим на a
унікальна властивість об'єкта, така як його адреса пам'яті, а не в об'єкті
себе. Це має перевагу, оскільки забезпечує інкапсуляцію атрибутів об’єктів
їхні дані не зберігаються в самому об'єкті.
Ця техніка була популярна деякий час (і була рекомендована Деміаном Конвеєм Perl кращий
Практики), але так і не досяг загального прийняття. Модуль Object::InsideOut на CPAN
забезпечує комплексну реалізацію цієї методики, і ви можете побачити її чи ін
модулі навиворіт у дикій природі.
Ось простий приклад техніки з використанням основного модуля Hash::Util::FieldHash.
Цей модуль додано до ядра, щоб підтримувати реалізації об’єктів навиворіт.
час упаковки;
використовувати суворий;
використовувати попередження;
використовуйте Hash::Util::FieldHash 'fieldhash';
хеш поля мій %time_for;
під новий {
мій $class = shift;
my $self = bless \( my $object ), $class;
$time_for{$self} = час;
повернути $self;
}
підепоха {
my $self = зміна;
повернути $time_for{$self};
}
my $time = Time->new;
надрукувати $time->epoch;
Псевдо-хеші
Псевдохеш-функція була експериментальною функцією, представленою в попередніх версіях Perl
і видалено в 5.10.0. Псевдохеш — це посилання на масив, до якого можна отримати доступ за допомогою
іменовані ключі, як хеш. Ви можете натрапити на якийсь код у дикій природі, який його використовує. Див
поля pragma для отримання додаткової інформації.
Використовуйте perlobj онлайн за допомогою сервісів onworks.net