OOP Perl pasando @_ al segundo método

#! /usr/bin/perl

# this is the object tester

{package Hate;
sub status {
my $class = shift;
print "-- $_[0] $_[1] $_[2]\n";
print "$class exists and ", $class->stats($_[0]), "and ", $class->type($_[1]), "and ",     $class->location($_[2]);
}
}

{package Grudge;
@ISA = "Hate";
sub stats{"$_[0]\n"}
sub type{"$_[0]\n"}
sub location{"$_[0]\n"}
}

Hate::status("Grudge", @ARGV);

corrí ./programa uno dos tres

esta salida es lo que esperaba Grudge existe y uno y dos y tres

esto es lo que tengo El rencor existe y el rencor y el rencor y el rencor

Sin embargo, cuando uso este script

#! /usr/bin/perl

# this is the object tester

{package Hate;
sub status {
my $class = shift;
print "-- $_[0] $_[1] $_[2]\n";
print "$class exists and ", $class->stats($_[0]), "and ", $class->type($_[1]), "and ",     $class->location($_[2]);
}
}

{package Grudge;
@ISA = "Hate";
sub stats{"$_[1]\n"}
sub type{"$_[1]\n"}
sub location{"$_[1]\n"}
}

Hate::status("Grudge", @ARGV);

Esto funcionó.

preguntado el 01 de julio de 12 a las 18:07

¿Odia o le guarda rencor el código de sangría y las mayúsculas en las oraciones? -

Realmente no estoy tratando de sonar sarcástico, pero ¿por qué esperas one two three? Quizás si explica por qué esta es su expectativa, podríamos entender cuál es la desconexión. También lo que está en @ARGV? -

1 Respuestas

En tu primer ejemplo, $class->stats($_[0]) se llama como Método y se pasa un objeto como primer argumento, que debe ser desplazado como lo hizo en Hate::status. Es por eso $_[1] funciona: porque el primer argumento del método es en realidad el segundo elemento en @_ (después $self).

Las cosas se vuelven mucho más claras y manejables si desentraña los argumentos de @_ al comienzo de la función, por ejemplo

{
    package Hate;
    sub status {
        my ($class, $stats, $type, $location) = @_;
        print "-- $stats $type $location\n";
        print "$class exists and ", $class->stats($stats), ...;
    }
}

{
    package Grudge;
    our @ISA = qw(Hate);
    sub stats { my ($self, $stats) = @_; $stats; }
    sub type { my ($self, $type) = @_; $type; }
    sub location { my ($self, $location) = @_; $location; }
}

Hate::status('Grudge', @ARGV);

Como nota al margen, su uso de objetos no es típico: si proporcionó más código, es posible que podamos proporcionar una solución Perl más idiomática. Por ejemplo, ninguno de sus objetos tiene constructores, y en este momento los tres métodos Grudge parecen hacer lo mismo. Tampoco está claro por qué Grudge es una subclase de Hate (como lo indica el @ISA).

si realmente no quieres Grudge para pasar su propio nombre como argumento, puede llamar a sus métodos como funciones a través de &{$class . '::stats'}() pero tendrás que deshabilitar strict subs. Por lo general, es mejor llamar a los métodos como lo está haciendo ahora.

Respondido 01 Jul 12, 18:07

Por lo general, eludo la invocación del método haciendo my $method = $class->can('stats') entonces cuando llamas $method->(@args) no pasa la autorreferencia. Limpiador y strict-seguro. ;-)- joel berger

@JoelBerger: Sí, pero aun así, ¿por qué querrías hacerlo? - ilmari karonen

Ok, la verdad sea dicha, no evito la invocación de métodos, necesito referencias a métodos, y los llamo con $method->($instance, @args), pero el uso no es diferente. Por qué @rjh hace esto, no lo sé. - joel berger

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.