2012-05-28 5 views
7

De perldoc perlobj (citado en este excelente answer):¿Cuál es exactamente la diferencia entre llamar a un método a través de "->" vs pasar clase/objeto como primer parámetro?

my $fred = Critter->find("Fred"); 
$fred->display("Height", "Weight"); 

... el código anterior es principalmente equivalente a:

my $fred = Critter::find("Critter", "Fred"); 
Critter::display($fred, "Height", "Weight"); 

¿Cuál es exactamente la diferencia, dejando a un lado el error ¿se está asegurando de que el primer parámetro sea un objeto bendecido o un nombre de clase válido? P.ej. ¿Por qué es en su mayoría pero no exactamente lo mismo?

+2

"dejando a un lado la comprobación de errores para asegurarse de que el primer parámetro es un objeto bendito o un nombre de clase válido" - que es algo muy importante propiedad para estar dejando de lado, ¿no? – Mat

+0

@Mat - Correcto. Lo dejé fuera debido a su obviedad, no por falta de importancia. – DVK

Respuesta

15

Say Critter es una subclase que no define find o display -o ambos! La correspondencia no es uno a uno porque las sub llamadas cableadas no realizan búsquedas de métodos, como explica la documentación de perlobj.

¿Cómo sabe Perl en qué paquete está la subrutina? Al mirar el lado izquierdo de la flecha, que debe ser un nombre de paquete o una referencia a un objeto, es decir, algo que ha sido bendecido con un paquete. De cualquier manera, ese es el paquete donde Perl comienza a buscar. Si ese paquete no tiene una subrutina con ese nombre, Perl comienza a buscarlo en cualquier clase base de ese paquete, y así sucesivamente.

Con un sub, tiene que saber exactamente dónde está estáticamente, o su programa será die. Para llamar a un método, solo necesita especificar dónde comenzar a buscarlo.

Por ejemplo:

#! /usr/bin/env perl 

package Critter; 
sub new { bless {}, shift } 
sub display { ref($_[0]) . " display" } 

package SuperCritter; 
@SuperCritter::ISA = qw/ Critter /; 

package main; 
my $super = SuperCritter->new; 

# one of these things is not like the other 
warn $super->display; 
warn Critter::display($super); 
warn SuperCritter::display($super); 

Salida:

SuperCritter display at ./call-demo line 14. 
SuperCritter display at ./call-demo line 15. 
Undefined subroutine &SuperCritter::display called at ./call-demo line 16.
+0

entonces, llamando 'Critter_subclass :: display' dará como resultado un error de tiempo de ejecución? (mostrando que probablemente mejoraría esta ya buena respuesta proporcionando un ejemplo concreto a una explicación teórica). – DVK

+0

@DVK ¡Buena sugerencia! Actualizado. –

+2

Una excelente respuesta, que he votado a favor, y sin embargo, logra demostrar que la respuesta a la pregunta es principalmente de herencia, sin usar la palabra herencia. :) – DavidO

Cuestiones relacionadas