В чем разница между новыми Some :: Class и Some :: Class-> new () в Perl?
Много лет назад я помню другого программиста, который консультировал это:
new Some::Class; # bad! (but why?) Some::Class->new(); # good!
К сожалению, теперь я не могу вспомнить причину. 🙁 Обе формы будут работать корректно, даже если конструктор фактически не существует в модуле Some :: Class, но вместо этого наследуется от родителя.
Ни одна из этих форм не такая же, как Some :: Class :: new (), которая не передаст имя classа в качестве первого параметра для конструктора, поэтому эта форма всегда некорректна.
- Как расширить модуль python? Добавление новых функций в пакет `python-twitter`
- Использовать requirejs и jquery, не сбивая глобальный jquery?
- Как вы используете данные модуля Fortran 90
- Как работает оператор модуля?
- DexIndexOverflowException только при выполнении тестов
Даже если эти две формы эквивалентны, я нахожу Some :: Class-> new () более понятным, поскольку он соответствует стандартным соглашениям о вызове метода в модуле, а в perl метод «новый» не является special – конструктор можно назвать чем угодно, а new () мог бы сделать что угодно (хотя, конечно, мы обычно ожидаем, что он будет конструктором).
- Понимание оператора модуля%
- ImportError на python 3, отлично работал на python 2.7
- Как я могу динамически включать модули Perl без использования eval?
- Может ли служба / модуль по умолчанию в приложении Google App Engine быть дочерним элементом нестандартного по структуре папок?
- Несколько модhive в Angularjs
- Как проверить, есть ли у меня модуль Perl перед его использованием?
- Как установить определенную версию набора модhive Perl?
- Android Studio: модуль не будет отображаться в «Редактирование конфигурации»
Использование 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 () для двух других (лучше?) Причин:
-
Как вы сказали, все другие методы classа принимают форму 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
если вы не выполняете динамическую программирование.