Благословить или не благословить, это мой вопрос!

Первый пост от новичка-пользователя. Кажется, каждый вопрос, который я задаю в Google, приводит меня сюда, и я всегда получаю отличный ответ на то, что я ищу; естественно, это была моя первая остановка, когда я начал размышлять об использовании благословения в Perl.

Я только что вошел в ООП Perl и только сегодня прочитал пост, спрашивающий, что делает благословение. Теперь я понимаю, что он ссылается на скаляр / хэш / массив с объектом, "присоединяя" его, если хотите.

В большинстве примеров классов, которые я вижу в Perl, они, кажется, не имеют свойств, которые я привык видеть в других языках...

{ package Person;
    my $property = "This is what I'm talking about :)";

    sub new { ... }
    ...
}

Итак, я создал тупой класс со свойством, чтобы посмотреть, что произойдет. Я сразу же присвоил свойству значение "NIL", а затем "Not Nil!" в конструкторе. Используя метод LIST, я смог напечатать свойство, и, как я и ожидал, оно напечатало "Not Nil!"

Мой вопрос: если свойства работают так же, как я ожидал, они будут работать (объявлено в теле), тогда зачем вообще использовать bless? Каково дополнительное преимущество наличия этой ссылки, когда вы можете просто создать скаляр / хэш / массив в качестве свойства или создать любые ссылки, которые вы хотите в качестве свойства?

Надеюсь, я объяснил то, что я пытаюсь спросить достаточно хорошо, очень зеленый с Perl:)

4 ответа

Ну, это не то, как вы создаете классы в Perl.

Ваш $property переменная определяется в области видимости пакета. Следовательно, в каждом классе будет только одна его копия, а не каждый объект, имеющий свою собственную копию.

Можно реализовать такой класс, используя объекты, основанные на хэше, длинным и сложным способом, как показано ниже:

#!/usr/bin/perl

package Person;

use strict; use warnings;

sub new {
    my $class = shift;
    my $self = {};
    bless $self => $class;

    my ($arg) = @_;
    for my $property ( qw( message ) ) {
        if ( exists $arg->{$property} ) {
            $self->$property($arg->{$property});
        }
    }
    return $self;
}

sub message {
    my $self = shift;
    return $self->{message} unless @_;
    my ($msg) = @_;
    $self->{message} = $msg;
}

package main;

my $person = Person->new({
    message => "This is what I'm talking about :)"
});

print $person->message, "\n";

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

Class:: Accessor является одним из таких служебных модулей.

Для программ, где время запуска не является проблемой, вы должны рассмотреть Moose. С помощью Moose вы можете написать выше:

#!/usr/bin/perl

package Person;

use Moose;

has 'message' => (is => 'rw', isa => 'Str');

__PACKAGE__->meta->make_immutable;
no Moose;

package main;

my $person = Person->new({
    message => "This is what I'm talking about :)"
});

print $person->message, "\n";

Вы должны прочитать perldoc perltoot и http://search.cpan.org/perldoc/Moose::Manual::Unsweetened для стандартного способа работы.

То, что вы сделали с помощью свойства $ в этом случае, объявлено как переменная в области видимости пакета "Персона". Вы изменяете это внутри (или снаружи, используя $Person::property) пакета, и любой объект, который на него ссылается, увидит обновленную переменную, поэтому он действует во многом как "статический атрибут (Java)" без какого-либо реального "частного" " объем. По соглашению, скрытые вещи в Perl ("private" или "protected") имеют префикс подчеркивания, но, конечно, это не обязательно.

На самом деле вы не создаете новый класс, как вы указали, с ключевым словом "package"; Вы можете использовать "пакет" без ООП вообще. Это просто создает отдельное "пространство имен".

Преимущество "благословения" переменной, почти всегда хэш-ссылки из того, что я видел, состоит в том, что вы можете иметь методы, как и любой другой язык ООП. Просто не забудьте благословить все, что вы возвращаете в подпрограмме new {} ("new" на самом деле не зарезервированное слово; это просто соглашение). Когда вы вызываете метод для "объекта" (благословенной структуры данных, такой как hashref), первым аргументом метода является сама структура данных. Итак, если у вас есть хеш-ссылка с именем $myobject, которая благословлена ​​для AwesomeClass, и вы определяете метод в AwesomeClass, называемый doSomethingAwesome, который должен принимать одну переменную, вам придется "сместить" @_ (который является списком аргументов подпрограмму или используйте $_[0]) для доступа к хеш-ссылке $ myobject. Python делает что-то подобное, и все языки так или иначе передают объектную ссылку на метод. (ключевое слово "this" во многих, см. также соглашение о вызовах "thiscall")

NB: я видел много Perl, бьющегося в мое время, которое было всего несколько лет как программист. Perl - это потрясающий язык, созданный очень умным лингвистом (Ларри Уоллом), и у него есть фанатичные последователи - он был более фанатичным за один раз, чем, возможно, Руби, но не настолько, как Дэвид Кореш). Perl делает вещи совсем не так, как многие языки, но если вы посмотрите на записи кода гольфа на этом и других сайтах, вы можете ясно увидеть, что многое можно сделать с очень небольшим количеством Perl (нет никаких гарантий в отношении разборчивости кода, особенно для новичков!)

Значение blessобъект получает возможность использовать методы из определенного пакета.

package MyClass;
sub answer { my ($self)=@_; return $self->{foo} * 42; }

package main;
my $object1 = { foo => 1, bar => "\t" };
my $object2 = bless { foo => 2, bar => "\t" }, "MyClass";

$ref1 = ref $object1;        #  'HASH'
$ref2 = ref $object2;        #  'MyClass'

$answer1 = $object1->answer;     # run time error
$answer2 = $object2->answer;     # calls MyClass::answer, returns 2 * 42 = 84

Тьфу... Ответ Синана слишком выучен на мой вкус, по крайней мере, за 12 часов:)

Так что я приведу более короткий и несколько менее перли, только ради разнообразия.

Насколько я могу судить, ваш вопрос не совсем о Perl, и его можно так же легко решить в другой форме: "Зачем использовать в нем C++ и ООП, когда в C уже есть структуры?"

Другими словами, вы, кажется, спрашиваете, в чем смысл использования парадигмы ООП.

Ответ, конечно, заключается в том, что это помогает решить некоторые проблемы разработки программного обеспечения проще, чем чисто процедурное программирование. Акцент на определенном - ООП не является панацеей для каждой проблемы, равно как и ЛЮБОЙ метод / подход / парадигма.

Использование ООП (в виде пакетов в качестве классов и благословенных хэшей в качестве объектов в Perl) позволяет вам пользоваться преимуществами наследования, полиморфизма и других OOPyish mumbo-jumbo, с которыми вы, вероятно, уже достаточно хорошо знакомы по опыту не-Perl OOP.

Можете ли вы сделать 100% того, что вы сделали бы с благословенным объектом с чистой структурой данных? Абсолютно. Будет ли 100% этого кода таким же простым / коротким / читаемым / обслуживаемым, как вы можете достичь с помощью объектов? Скорее всего, нет, хотя это зависит от того, насколько хорошо ваш ООП-код на самом деле использует преимущества, которые предоставляет ООП (кстати, я столкнулся с якобы ООП-кодом (Perl и нет), который на самом деле не использовал какие-либо преимущества парадигмы ООП и мог быть реализован. легче читать и понимать, если бы он был лишен ООП-хрома).

Другие вопросы по тегам