Много лет назад я помню, как мой товарищ-программист советовал это:
new Some::Class; # bad! (but why?)
Some::Class->new(); # good!
К сожалению, сейчас я не могу вспомнить / его причину. :( Обе формы будут работать правильно, даже если конструктор на самом деле не существует в модуле Some :: Class, а вместо этого унаследован от родителя где-то.
Ни одна из этих форм не совпадает с Some :: Class :: new (), который не передает имя класса в качестве первого параметра конструктору, поэтому эта форма всегда неверна.
Даже если эти две формы эквивалентны, я считаю Some :: Class-> new () гораздо более понятным, поскольку он следует стандартному соглашению для вызова метода в модуле, а в perl 'новый' метод не special - конструктор может быть вызван чем угодно, а new () может делать что угодно (хотя, конечно, мы обычно ожидаем, что это будет конструктор).





См. Косвенный синтаксис объекта в документации perlobj для объяснения его подводных камней. ответ Фрейдо покрывает один из них (хотя я стараюсь избегать этого с помощью явных скобок вокруг моих вызовов функций).
Ларри однажды пошутил, что это было сделано для того, чтобы C++ был доволен new, и хотя люди скажут вам никогда не использовать его, вы, вероятно, делаете это все время. Учти это:
print FH "Some message";
Вы когда-нибудь задумывались, что после дескриптора файла не было запятой? А в нотации косвенного объекта после имени класса нет запятой? Вот что здесь происходит. Вы можете переписать это как вызов метода при печати:
FH->print( "Some message" );
Возможно, вы испытали некоторую странность в print, если сделаете это неправильно. Установка запятой после явного дескриптора файла превращает его в аргумент:
print FH, "some message"; # GLOB(0xDEADBEEF)some message
К сожалению, у нас есть такая глупость в Perl. Не все, что вошло в синтаксис, было лучшей идеей, но именно это происходит, когда вы черпаете вдохновение из стольких источников. Некоторые идеи должны быть плохими.
Я не читал эту страницу руководства годами; Я действительно должен прочитать об этом больше. Жаль, что в новом Some :: Class так много подводных камней, потому что мне нравится, как он читается лучше, чем Some :: Class-> new (); Одна из вещей, которые мне больше всего нравятся в Perl, - это чувство естественного языка. Ну что ж, время для перемен ...
Использование new Some::Class называется «косвенным» вызовом метода, и это плохо, потому что вносит некоторую двусмысленность в синтаксис.
Одна из причин, по которой он может потерпеть неудачу, заключается в том, что у вас есть массив или хэш объектов. Вы могли ожидать
dosomethingwith $hashref->{obj}
быть равным
$hashref->{obj}->dosomethingwith();
но на самом деле он разбирается как:
$hashref->dosomethingwith->{obj}
что, вероятно, не то, что вы хотели.
Другая проблема заключается в том, что в вашем пакете есть функция с тем же именем, что и метод, который вы пытаетесь вызвать. Например, что, если какой-то модуль из use экспортировал функцию под названием dosomethingwith? В этом случае dosomethingwith $object неоднозначен и может привести к загадочным ошибкам.
Использование синтаксиса -> исключительно устраняет эти проблемы, потому что метод и то, над чем он должен работать, всегда ясны компилятору.
Синтаксис косвенного объекта не одобряется по уважительным причинам, но он не имеет ничего общего с конструкторами. У вас почти никогда не будет функции new () в вызывающем пакете. Скорее, вы должны использовать Package-> new () по двум другим (лучше?) Причинам:
Как вы сказали, все другие методы класса принимают форму Package-> method (), поэтому согласованность - хорошая вещь.
Если вы предоставляете аргументы конструктору или берете результат конструктора и немедленно вызываете на нем методы (если, например, вы не заботитесь о сохранении объекта), проще сказать, например,
$foo = Foo->new(type => 'bar', style => 'baz'); Bar->new->do_stuff;
чем
$foo = new Foo(type => 'bar', style => 'baz'); (new Bar)->do_stuff;
Другая проблема заключается в том, что new Some::Class происходит во время выполнения. Если возникает ошибка и вы никогда не переходите к этому оператору при тестировании, вы никогда не узнаете об этом, пока это не произойдет в рабочей среде. Лучше использовать Some::Class->new, если вы не занимаетесь динамическим программированием.
Еще одна отличная ссылка: Косвенный, но все же фатальный