Является ли хорошей практикой в ​​Perl, когда методы экземпляра вызывают друг друга по ссылке «$ self»? - PullRequest
5 голосов
/ 29 июня 2011

Должны ли экземпляры методов в Perl вызывать друг друга так:

package BlaBla;

sub foo {
    my($self) = @_;
    #do something awesome;
}

sub bar {
    my($self) = @_;
    foo();
}

Или вот так:

package BlaBla;

sub foo {
    my($self) = @_;
    #do something awesome
}

sub bar {
    my($self) = @_;
    $self->foo();
}

Спасибо всем за потраченное время.

Ответы [ 5 ]

15 голосов
/ 29 июня 2011

Да, вы должны включить $self - если вы этого не сделаете, полиморфизм не будет работать, потому что каждый метод будет искать все вызовы в своем собственном пакете, даже если они переопределены в подклассе. Хуже того, если указанный метод унаследован от родителя и не переопределен в текущем подклассе, программа будет die, потому что его нет в этом пакете. И это даже если вы помните, что пытались обмануть механизм OO Perl, передавая $self в качестве первого параметра.

9 голосов
/ 29 июня 2011

Если foo () - это метод, который можно вызывать из других мест, вы всегда должны вызывать его как метод, иначе наследующие от вас классы не смогут его переопределить, и вы заставите свой foo () проверить, вызывается ли он методичным или функциональным способом.

С другой стороны, если foo () - это просто некоторый вспомогательный код, который используют несколько ваших методов, и он довольно специфичен для вашей реализации класса, то вы можете вызывать его напрямую, но тогда он действительно должен вызываться напрямую и может захотеть пометить его как частную функцию, доступную классу, добавив перед его именем знак подчеркивания: _foo ().

8 голосов
/ 29 июня 2011

Первый не будет работать, если вы используете $self где-то в foo(), потому что он не получает никаких аргументов.Вы могли бы вызвать foo($self), но вам почти наверняка лучше использовать фактический синтаксис вызова метода, а не выбрасывать OO-функции Perl из окна и просто рассматривать foo() как функцию, которая вызывает первый параметр "$self».

4 голосов
/ 29 июня 2011

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

3 голосов
/ 30 июня 2011

Первый подход не будет работать так, как написано.

sub bar {
  my($self) = @_;
  foo();
}

Здесь вы явно вызываете foo как функцию без аргументов через этот оператор foo();.Это создаст пустой локальный массив @_.Первый оператор в foo извлекает $self в качестве первого элемента из этого локального @_, поэтому $self не определен с этим механизмом.

Вам необходимо передать $self в качестве аргумента foo.Есть (как минимум) пять способов сделать это:

  1. Обозначение стрелки: Вызвать foo через $self->foo();
  2. Косвенное обозначение: Вызвать foo через foo $self;
  3. Обычный вызов подпрограммы: Invoke foo via foo($self);
  4. Предполагаемые аргументы: Invoke foo via foo $self; Этот параметр можно использовать, только если foo был предварительно объявлен с прототипом функции.
  5. Не создавайте этот локальный массив @_.Позвольте foo добавить в массив bar @_.Вызвать foo через &foo; Обратите внимание, что в этом вызове нет скобок.

Относительно опции № 5: она существует.Не используйте это.Это доставит вам неприятности.

Разница между # 2 и # 4 становится очевидной, когда foo принимает дополнительные аргументы.Косвенная нотация становится (например) foo $self 42;, в то время как подразумеваемая форма становится foo $self, 42; Косвенная нотация (вариант 2) теперь настоятельно не рекомендуется.Варианты 3 и 4 также не рекомендуется использовать с методами.

Это оставляет вариант № 1.Несмотря на то, что обозначение стрелки является просто синтаксическим сахаром, оно очень много значит для читателя.Используйте это.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...