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

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

Я только что попал в Perl OOP и только сегодня прочитал сообщение о том, что делает благословение. Теперь я понимаю, что он ссылается на массив scalar/hash/array на объект, "прикрепляя" его, если хотите.

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

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

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

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

Надеюсь, я объяснил, что я пытаюсь спросить достаточно хорошо, очень зеленый с 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 и Moose::Manual::Unsweetened для стандартного способа делать вещи.


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

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

Преимущество "благословения" переменной, почти всегда хеш-ссылки из того, что я видел, заключается в том, что у вас могут быть методы, как и любой другой язык ООП. Просто помните, чтобы благословлять все, что вы вернете в новой {} подпрограмме ( "новый" на самом деле не является зарезервированным словом, а просто соглашением). Когда вы вызываете метод в "объекте" (блаженной структуре данных, такой как hashref), первым аргументом метода является сама структура данных. Итак, если у вас есть hashref, называемый $myobject, который благословлен AwesomeClass, и вы определяете метод в AwesomeClass, называемый doSomethingAwesome, который должен принимать одну переменную, вам придется "сдвигать" @_ (это список аргументов подпрограмму или использовать $_ [0]) для доступа к $myobject hashref. 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 часов:)

Итак, я дам более короткий и несколько меньший Perly, просто ради разнообразия.

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

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

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

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

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

licensed under cc by-sa 3.0 with attribution.