Благословить или не благословить, это мой вопрос! - PullRequest
6 голосов
/ 11 августа 2010

первое сообщение от новичка-пользователя. Кажется, каждый вопрос, который я задаю в 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 ]

11 голосов
/ 11 августа 2010

Ну, это не то, как вы создаете классы в 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 и Moose :: Manual :: Unsweeteed для стандартного способа ведения дел.

8 голосов
/ 11 августа 2010

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

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

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

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

5 голосов
/ 11 августа 2010

Значение 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
4 голосов
/ 11 августа 2010

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

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

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

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

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

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

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

...