При написании модуля Perl мне нужно специально проверять наличие экземпляра объекта во всех моих методах? - PullRequest
4 голосов
/ 25 октября 2009

Я пишу модуль, который имеет несколько методов. Давайте рассмотрим это:

package MyPackage;
sub new {
 ...
}

sub do_your_job {
 ...
}
1;

Что мешает кому-то звонить do_your_job как MyPackage->do_your_job вместо $obj->do_your_job? Нужно ли проверять каждый метод, на который я получаю ссылку в качестве первого аргумента?

Ответы [ 6 ]

9 голосов
/ 25 октября 2009

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

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

5 голосов
/ 25 октября 2009

Теоретически короткие ответы: «Ничего» и «Это неплохая идея».

Однако на практике документация - это то, что решает эти проблемы. В сообществе Perl есть обычная вежливость, которая инструктирует разработчиков использовать модули только так, как они задокументированы.

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

5 голосов
/ 25 октября 2009

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

То же самое относится и к аргументам, отличным от неявного аргумента объекта / класса при вызове метода. У вас может быть параметр, который должен быть ссылкой на массив, или положительным целым числом, меньшим 10, или объектом некоторого заданного типа, или просто чем-то еще. Один из способов - предположить, что абоненты следуют документации; другой - ничего не доверять.

3 голосов
/ 25 октября 2009

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

 sub some_method {
      my( $class ) = @_;
      croak( "This is a class method only" ) if ref $class;
      ...
      }

Хотя я, как правило, не очень беспокоюсь, вы можете проверить наличие экземпляра, прежде чем пытаться что-либо разыменовать:

 sub some_instance_method {
      my( $self ) = @_;
      croak( "This is an instance method only" ) unless ref $self;

      $self->{some_attr};
      }

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

3 голосов
/ 25 октября 2009

Как уже говорили другие, документируйте, что делает ваш модуль, и доверяйте пользователю. Однако стоит подумать о философской разнице между вызовом класса и вызовом объекта. Если ваш модуль Perl предоставляет способ создания объектов, многие из методов в этом классе, вероятно, будут полагаться на данные, специфичные для отдельного объекта. Вероятно, это наиболее распространенный способ вызова методов: если у вас есть объект, вы просто делаете $object->method(…). Однако вполне вероятно, что некоторые методы класса являются общими и не нуждаются в данных от конкретного объекта. Они часто вызываются с использованием имени пакета, и это чаще всего наблюдается при вызове метода new(), такого как LWP::UserAgent->new().

Удобно, Perl позволяет вам обрабатывать эти два случая одинаково, используя что-то вроде my $self = shift; в начале метода: если метод вызывается для объекта, $self получает значение ссылки на объект , если вызывается в классе, $self получает имя пакета.

Даже если метод вызывается для класса, поэтому $self содержит имя пакета, вы все равно можете вызывать другие методы этого пакета таким же образом , выполнив $self->method(…). Это тогда совместимо с вызовом исходного метода для определенного объекта, поэтому все держится вместе.

Как один из примеров, пакет Perl Math :: BigInt включает в себя довольно много методов, некоторые из которых предназначены для вызова в самом пакете (классе) (например, new()), некоторые из которых должны вызываться для отдельных объектов (например, round()), а некоторые для любого (например, accuracy()).

Мораль: все зависит от функциональности метода в том, способен ли он иметь разумное значение. Разумно предположить, что метод any вызывается с ожиданием того, что он будет делать то, для чего вы его рекламируете. Однако не требует вызова метода для объекта, когда может иметь смысл вызывать этот метод для самого класса.

0 голосов
/ 25 октября 2009

Используйте Лось и забудьте о сантехнике.

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