В чем разница между новыми Some :: Class и Some :: Class-> new () в Perl?

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

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

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

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

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

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

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

 dosomethingwith $hashref->{obj} 

быть равным

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

но он фактически анализирует:

 $hashref->dosomethingwith->{obj} 

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

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

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

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

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

 print FH "Some message"; 

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

 FH->print( "Some message" ); 

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

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

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

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

  1. Как вы сказали, все другие методы classа принимают форму 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; 

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

  • Есть ли какая-либо однолинейная аналогия в ES6 для ES5 `module.exports = require ('./ inner.js')`?
  • Как я могу использовать новый модуль Perl без разрешения на установку?
  • Мощность модуля больших чисел
  • Использование библиотеки aar приводит к отсутствию зависимостей с помощью api в Gradle 4.x
  • Лучший способ загрузить модуль / class из папки lib в Rails 3?
  • Как установить модуль CPAN в локальный каталог?
  • addr2line на модуле ядра
  • TypScript ReferenceError: экспорт не определен
  • Что такое модуль в .NET?
  • Как использовать модуль для float / double?
  • Что происходит, когда модуль импортируется дважды?
  • Давайте будем гением компьютера.