В чем разница между новыми Some:: Class и Some:: Class-> new() в Perl?
Много лет назад я помню другого программиста, который консультировал это:
new Some::Class; # bad! (but why?)
Some::Class->new(); # good!
К сожалению, теперь я не могу вспомнить причину.:( Обе формы будут работать корректно, даже если конструктор фактически не существует в модуле Some:: Class, но вместо этого наследуется от родителя где-то.
Ни одна из этих форм не такая же, как Some:: Class:: new(), которая не передаст имя класса в качестве первого параметра для конструктора, поэтому эта форма всегда неверна.
Даже если эти две формы эквивалентны, я нахожу Some:: Class- > new() более понятным, так как это следует стандартным соглашениям о вызове метода в модуле, а в perl - "новом", метод не является специальным - конструктор можно назвать чем угодно, а new() мог бы что-либо сделать (хотя, конечно, мы обычно ожидаем, что он будет конструктором).
Ответы
Ответ 1
Использование new Some::Class
называется "косвенным" вызовом метода, и это плохо, потому что оно вводит некоторую двусмысленность в синтаксис.
Одна из причин, по которой он может потерпеть неудачу, заключается в том, что у вас есть массив или хэш объектов. Вы можете ожидать
dosomethingwith $hashref->{obj}
чтобы быть равным
$hashref->{obj}->dosomethingwith();
но он фактически анализирует как:
$hashref->dosomethingwith->{obj}
который, вероятно, не тот, который вам нужен.
Другая проблема заключается в том, что в вашем пакете есть функция с тем же именем, что и метод, который вы пытаетесь вызвать. Например, что, если какой-то модуль, который вы use
'd экспортировали функцию с именем dosomethingwith
? В этом случае dosomethingwith $object
является неоднозначным и может приводить к загадочным ошибкам.
Использование синтаксиса ->
исключительно устраняет эти проблемы, поскольку метод и то, что вы хотите, чтобы метод работал, всегда ясны компилятору.
Ответ 2
См. Синтаксис косвенных объектов в документации perlobj для объяснения ее ошибок. freido answer охватывает один из них (хотя я стараюсь избегать этого с явным parens вокруг моих вызовов функций).
Ларри однажды пошутил, что он должен был сделать С++ счастливым о new
, и, хотя люди скажут вам, что никогда не будут использовать его, вы, вероятно, все это делаете. Рассмотрим это:
print FH "Some message";
Вы когда-нибудь задумывались о том, что после дескриптора файла не было запятой? И нет никакой запятой после названия класса в косвенной объектной нотации? Что здесь происходит. Вы можете переписать это как вызов метода при печати:
FH->print( "Some message" );
Возможно, вы испытали какую-то странность в print
, если вы сделали это неправильно. Помещение запятой после явного дескриптора файла превращает его в аргумент:
print FH, "some message"; # GLOB(0xDEADBEEF)some message
К сожалению, у нас есть эта глупость в Perl. Не все, что попало в синтаксис, было лучшей идеей, но это то, что происходит, когда вы тянете из стольких источников вдохновения. Некоторые из идей должны быть плохими.
Ответ 3
Синтаксис косвенного объекта неодобрен по причинам, но это не имеет ничего общего с конструкторами. У вас почти никогда не будет функции 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;
Ответ 4
Другая проблема заключается в том, что new Some::Class
происходит во время выполнения. Если есть ошибка, и вы не проверяете ветки на это утверждение, вы никогда не узнаете об этом до тех пор, пока это не произойдет в процессе производства. Лучше использовать Some::Class->new
, если вы не выполняете динамическую программирование.