¿Cuál es la diferencia entre los nuevos Some :: Class y Some :: Class-> new () en Perl?

Hace muchos años recuerdo a un compañero progtwigdor aconsejando esto:

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

Lamentablemente, ahora no puedo recordar la razón por la cual. 🙁 Ambas formas funcionarán correctamente incluso si el constructor no existe realmente en el módulo Some :: Class, sino que se hereda de un elemento primario en alguna parte.

Ninguna de estas formas es igual a Some :: Class :: new (), que no pasará el nombre de la clase como primer parámetro al constructor, por lo que este formulario siempre es incorrecto.

Incluso si las dos formas son equivalentes, me parece que Some :: Class-> new () es mucho más claro, ya que sigue la convención estándar para llamar a un método en un módulo, y en perl, el método ‘nuevo’ no es especial: un constructor podría llamarse cualquier cosa, y new () podría hacer cualquier cosa (aunque, por supuesto, generalmente esperamos que sea un constructor).

El uso de una new Some::Class se denomina invocación de método “indirecto”, y es mala porque introduce cierta ambigüedad en la syntax.

Una razón por la que puede fallar es si tiene una matriz o hash de objetos. Usted puede esperar

 dosomethingwith $hashref->{obj} 

ser igual a

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

pero en realidad analiza como:

 $hashref->dosomethingwith->{obj} 

que probablemente no sea lo que querías

Otro problema es si sucede que hay una función en su paquete con el mismo nombre que el método que está tratando de llamar. Por ejemplo, ¿qué dosomethingwith si algún módulo que use ‘d exportó una función llamada dosomethingwith ? En ese caso, dos dosomethingwith $object es ambiguo y puede dar lugar a errores desconcertantes.

El uso de la syntax -> elimina estos problemas exclusivamente, ya que el método y el método sobre el que desea que el método estén siempre claros para el comstackdor.

Ver Sintaxis de Objeto Indirecto en la documentación de perlobj para una explicación de sus dificultades. La respuesta de freido cubre uno de ellos (aunque tiendo a evitar eso con parens explícitos alrededor de mis llamadas a funciones).

Larry una vez bromeó que estaba allí para hacer que C ++ se sintiera feliz por lo new , y aunque la gente te dirá que nunca lo uses, probablemente lo estés haciendo todo el tiempo. Considera esto:

 print FH "Some message"; 

¿Alguna vez te has preguntado si no había una coma después del identificador de archivos? ¿Y no hay una coma después del nombre de la clase en la notación indirecta del objeto? Eso es lo que está pasando aquí. Podrías reescribir eso como una llamada a método en la impresión:

 FH->print( "Some message" ); 

Es posible que haya experimentado alguna rareza en la print si lo hace mal. Poner una coma después del manejador de archivo explícito lo convierte en un argumento:

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

Lamentablemente, tenemos esta tontería en Perl. No todo lo que entró en la syntax fue la mejor idea, pero eso es lo que sucede cuando recurre a tantas fonts para obtener inspiración. Algunas de las ideas tienen que ser las malas.

La syntax del objeto indirecto está mal vista, por buenas razones, pero eso no tiene nada que ver con los constructores. Casi nunca va a tener una función nueva () en el paquete de llamadas. En su lugar, debe usar Package-> new () por otros dos motivos (¿mejor?):

  1. Como dijiste, todos los otros métodos de clases toman la forma Package-> method (), por lo que la consistencia es una buena cosa

  2. Si está suministrando argumentos al constructor, o está tomando el resultado del constructor y llamando inmediatamente a los métodos (por ejemplo, si no le importa mantener el objeto), es más fácil decir, por ejemplo

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

que

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

Otro problema es que el new Some::Class ocurre en tiempo de ejecución. Si hay un error y la prueba nunca se bifurca a esta afirmación, nunca se sabe hasta que ocurre en producción. Es mejor utilizar Some::Class->new menos que esté haciendo una progtwigción dinámica.