В чем разница между новыми Some :: Class и Some :: Class-> new () в Perl? - PullRequest
27 голосов
/ 09 января 2009

Много лет назад я помню одного программиста, который советовал:

new Some::Class;    # bad! (but why?)

Some::Class->new(); # good!

К сожалению, теперь я не могу вспомнить его причину, почему. :( Обе формы будут работать правильно, даже если конструктор фактически не существует в модуле Some :: Class, а вместо этого унаследован от родительского объекта.

Ни одна из этих форм не совпадает с Some :: Class :: new (), которая не будет передавать имя класса в качестве первого параметра конструктору - поэтому эта форма всегда неверна.

Даже если эти две формы эквивалентны, я считаю, что Some :: Class-> new () гораздо более понятна, так как она следует стандартному соглашению для вызова метода в модуле, а в perl, 'new' Метод не является специальным - конструктор может вызываться как угодно, а new () может делать что угодно (хотя, конечно, мы обычно ожидаем, что он будет конструктором).

Ответы [ 4 ]

26 голосов
/ 10 января 2009

Использование new Some::Class называется «косвенным» вызовом метода, и это плохо, поскольку вносит некоторую двусмысленность в синтаксис.

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

dosomethingwith $hashref->{obj}

будет равно

$hashref->{obj}->dosomethingwith();

но на самом деле он анализируется как:

$hashref->dosomethingwith->{obj}

что, вероятно, не то, что вы хотели.

Другая проблема заключается в том, что в вашем пакете есть функция с тем же именем, что и метод, который вы пытаетесь вызвать. Например, что если какой-то модуль, который вы use экспортировали в функцию с именем dosomethingwith? В этом случае dosomethingwith $object является неоднозначным и может привести к удивительным ошибкам.

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

21 голосов
/ 09 января 2009

См. Синтаксис косвенного объекта в документации perlobj для объяснения его подводных камней. ответ freido охватывает один из них (хотя я склонен избегать этого с явными паренами вокруг моих вызовов функций).

Ларри однажды пошутил, что именно там C ++ чувствует себя счастливым по поводу new, и хотя люди скажут вам никогда не использовать его, вы, вероятно, делаете это постоянно. Учтите это:

print FH "Some message";

Вы когда-нибудь задумывались над тем, что после дескриптора файла не было запятой? И нет запятой после имени класса в косвенной записи объекта? Вот что здесь происходит. Вы можете переписать это как вызов метода при печати:

FH->print( "Some message" );

Возможно, вы испытали некоторую странность в print, если поступили неправильно. Помещение запятой после явного описателя файла превращает его в аргумент:

print FH, "some message";     # GLOB(0xDEADBEEF)some message

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

4 голосов
/ 10 января 2009

Косвенный объектный синтаксис не одобрен, по уважительным причинам, но это не имеет ничего общего с конструкторами. Вы почти никогда не будете иметь функцию new () в вызывающем пакете. Скорее, вы должны использовать Package-> new () по двум другим (лучше?) Причинам:

  1. Как вы сказали, все другие методы класса принимают форму Package-> method (), поэтому согласованность - это хорошо

  2. Если вы предоставляете аргументы в конструктор, или вы берете результат конструктора и немедленно вызываете методы для него (если, например, вам не нужно хранить объект вокруг), проще скажем, например

$foo = Foo->new(type => 'bar', style => 'baz');
Bar->new->do_stuff;

чем

$foo = new Foo(type => 'bar', style => 'baz');
(new Bar)->do_stuff;
0 голосов
/ 10 января 2009

Другая проблема заключается в том, что new Some::Class происходит во время выполнения. Если есть ошибка, и вы тестируете никогда не переходите к этому утверждению, вы никогда не узнаете об этом, пока это не произойдет в производстве. Лучше использовать Some::Class->new, если вы не занимаетесь динамическим программированием.

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