Perl: Class :: Struct без ограничений типа - PullRequest
2 голосов
/ 10 августа 2011

Я играю с некоторым кодом, в котором объединение кодовых ссылок с переменными имеет смысл, но использование полноценного OOD - нет. По сути, я пишу функциональный код, но прибегаю к нескольким структурам в стиле ОО, чтобы инкапсулировать вещи, в которых имеет смысл состояние действительно . Снаружи это в основном функции без состояния.

Использование Moose для этого было бы равносильно наказанию коллег, которые иногда опаздывали, с помощью автоматической винтовки: совершить излишнее убийство несколькими способами. Так что избавьте меня от 'ALL PERL OOP ДОЛЖНЫ ИСПОЛЬЗОВАТЬ БОЛЬШЕ СЕЙЧАС !!!' мантра.

Итак, я побежал в хороший старый класс blessed-hashref, чтобы выполнить мои ставки, но обнаружил, что написание кода доступа - это боль, и я не хотел использовать нестандартные модули для того, что по сути является очень тривиальной задачей. .

После перемещения по страницам на http://perldoc.perl.org, Я наткнулся на Class :: Struct и Object :: Accessor, которые являются основными модулями, облегчающими создание атрибутов OO. Отлично, хотя я. Но ...

Object :: Accessor показался мне идеальным билетом, но я просто использовал его подпрограмму mk_accessor в конструкторе, которая не казалась столь же элегантной, как использование Class :: Struct во время компиляции, который также написал мой конструктор по умолчанию для меня. В общем, я предпочел Class :: Struct объекту :: Accessor, потому что позволял немного меньше шаблонного и имел более декларативный синтаксис.

Сравнение с использованием тривиальных примеров, если вам интересно:

Использование Class :: Struct:

#!/usr/bin/perl

use 5.014;
use autodie;
use strict;
use warnings;

package Account {
    use Class::Struct
        first_name   => '$',
        last_name    => '$',
        age_in_years => '$',
        activated    => '$',
        ;

    sub formatted {
        my ($self_ref) = @_;
        return sprintf
            "First name:   %s\n" .
            "Last name:    %s\n" .
            "Age in Years: %d\n" .
            "Activated:    %s",
            $self_ref->first_name,
            $self_ref->last_name,
            $self_ref->age_in_years,
            $self_ref->activated || 'No'
            ;
    }
}

my $account = Account->new;

$account->first_name('Tom');
$account->last_name('Smith');
$account->age_in_years(16);
$account->activated('Yes');

say $account->formatted

Использование Object :: Accessor:

use 5.014;
use autodie;
use strict;
use warnings;

package Account {
    use base 'Object::Accessor';

    sub new {
        my ($type) = @_;
        my $self = bless { }, $type;
        $self->mk_accessors(qw(first_name last_name age_in_years activated));
        return $self;
    }

    sub formatted {
        my ($self_ref) = @_;
        return sprintf
            "First name:   %s\n" .
            "Last name:    %s\n" .
            "Age in Years: %d\n" .
            "Activated:    %s",
            $self_ref->first_name,
            $self_ref->last_name,
            $self_ref->age_in_years,
            $self_ref->activated || 'No'
            ;
    }
}

my $account = Account->new;

$account->first_name('Tom');
$account->last_name('Smith');
$account->age_in_years(16);
$account->activated('Yes');

say $account->formatted;

Действительно, оба вполне приемлемы, но первый немного более чистый IMO. Я хочу знать, могу ли я использовать Class :: Struct без указания ограничений типа?

Мне они не нужны в контексте, которым я их использую, но, похоже, я не могу просто добавить средства доступа без указания типовых ограничений рядом с ними. Без сомнения, я теряю производительность из-за ненужной проверки типов.

Если это невозможно, я просто буду придерживаться Object :: Accessor. Но возможны ли средства доступа без ограничений типа с Class :: Struct?

1 Ответ

1 голос
/ 10 августа 2011

Я предпочитаю Class :: Struct для задачи. Я обычно использую только скаляры, у них нет проверки, и вы можете хранить для них что угодно (например, arrayref или hashref).

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

package Account;
use Class::Struct
    map { $_ => '$' } qw(
        first_name
        last_name
        age_in_years
        activated
        items
    );

package main;

my $acc = Account->new(
    first_name => 'John',
    last_name  => 'Doe',
    items      => ['a' .. 'z']
);
...