Современное ООП в Perl
Полное руководство по объектно-ориентированному программированию в Perl с использованием современных практик и модулей.
1. Основы ООП в Perl
1.1 Классы и объекты
package Person;
use strict;
use warnings;
sub new {
my ($class, %args) = @_;
my $self = {
name => $args{name} // 'Unknown',
age => $args{age} // 0,
};
return bless $self, $class;
}
sub name {
my ($self) = @_;
return $self->{name};
}
sub age {
my ($self) = @_;
return $self->{age};
}
1;
Базовый класс Person с конструктором и методами доступа.
1.2 Наследование
package Employee;
use strict;
use warnings;
use parent 'Person';
sub new {
my ($class, %args) = @_;
my $self = $class->SUPER::new(%args);
$self->{salary} = $args{salary} // 0;
return $self;
}
sub salary {
my ($self) = @_;
return $self->{salary};
}
Класс Employee, наследующий от Person и добавляющий свойство salary.
2. Современные практики
2.1 Использование Moose
package User;
use strict;
use warnings;
use Moose;
has 'username' => (
is => 'ro',
isa => 'Str',
required => 1,
);
has 'email' => (
is => 'rw',
isa => 'Str',
required => 1,
);
has 'password' => (
is => 'rw',
isa => 'Str',
required => 1,
trigger => sub {
my ($self, $new) = @_;
$self->_hash_password($new);
},
);
sub _hash_password {
my ($self, $password) = @_;
# Хеширование пароля
$self->{password} = sha256_hex($password);
}
__PACKAGE__->meta->make_immutable;
Современный класс с использованием Moose, включая атрибуты, типы и триггеры.
2.2 Роли (Traits)
package Role::Loggable;
use strict;
use warnings;
use Moose::Role;
has 'logger' => (
is => 'ro',
isa => 'Logger',
handles => {
'log_info' => 'info',
'log_error' => 'error',
},
);
sub log_action {
my ($self, $action) = @_;
$self->log_info("Action performed: $action");
}
Роль Loggable, добавляющая функциональность логирования.
3. Продвинутые возможности
3.1 Метапрограммирование
package Meta::Class;
use strict;
use warnings;
use Moose;
sub add_method {
my ($class, $name, $code) = @_;
$class->meta->add_method($name, $code);
}
sub add_attribute {
my ($class, $name, %spec) = @_;
$class->meta->add_attribute($name, %spec);
}
__PACKAGE__->meta->make_immutable;
Пример метапрограммирования с использованием Moose.
3.2 Декораторы
package Decorator::Cache;
use strict;
use warnings;
use Moose;
has 'cache' => (
is => 'ro',
isa => 'HashRef',
default => sub { {} },
);
sub decorate {
my ($self, $method) = @_;
return sub {
my ($object, @args) = @_;
my $key = join(':', $method, join(',', @args));
return $self->{cache}{$key} if exists $self->{cache}{$key};
$self->{cache}{$key} = $object->$method(@args);
};
}
Декоратор для кэширования результатов методов.
4. Тестирование ООП кода
4.1 Модульные тесты
use strict;
use warnings;
use Test::More;
use Test::Moose;
use Person;
my $person = Person->new(name => 'John', age => 30);
does_ok($person, 'Person', 'Объект является экземпляром Person');
is($person->name, 'John', 'Имя установлено корректно');
is($person->age, 30, 'Возраст установлен корректно');
done_testing();
Тестирование класса Person с использованием Test::More и Test::Moose.
4.2 Тестирование ролей
use strict;
use warnings;
use Test::More;
use Test::Moose;
use Role::Loggable;
my $role = Role::Loggable->meta;
does_ok($role, 'Moose::Role', 'Role::Loggable является ролью');
has_attribute_ok($role, 'logger', 'Роль имеет атрибут logger');
can_ok($role, 'log_action', 'Роль имеет метод log_action');
done_testing();
Тестирование роли Loggable с использованием Test::Moose.
5. Лучшие практики
5.1 Иммутабельные объекты
package Immutable::Point;
use strict;
use warnings;
use Moose;
has 'x' => (
is => 'ro',
isa => 'Int',
required => 1,
);
has 'y' => (
is => 'ro',
isa => 'Int',
required => 1,
);
sub move {
my ($self, $dx, $dy) = @_;
return Immutable::Point->new(
x => $self->x + $dx,
y => $self->y + $dy,
);
}
__PACKAGE__->meta->make_immutable;
Пример иммутабельного класса с использованием Moose.
5.2 Композиция вместо наследования
package Logger;
use strict;
use warnings;
use Moose;
sub info {
my ($self, $message) = @_;
print "[INFO] $message\n";
}
__PACKAGE__->meta->make_immutable;
package Service;
use strict;
use warnings;
use Moose;
has 'logger' => (
is => 'ro',
isa => 'Logger',
handles => ['info'],
required => 1,
);
sub process {
my ($self, $data) = @_;
$self->info("Processing data: $data");
# Обработка данных
}
__PACKAGE__->meta->make_immutable;
Пример использования композиции вместо наследования.
Это руководство охватывает основные аспекты современного ООП в Perl, включая:
- Базовые концепции классов и объектов
- Наследование и композицию
- Использование Moose для современного ООП
- Роли и трейты
- Метапрограммирование
- Декораторы
- Тестирование ООП кода
- Лучшие практики (иммутабельность, композиция)