? Tengo un programa en Perl que usa un paquete que obtuve de otra fuente. Una de las funciones del método devuelve un objeto de una clase desconocida. ¿Hay alguna forma de que obtenga todos los métodos posibles de un objeto sin mirar su implementación de clase?¿Existe alguna manera de conocer los métodos de una instancia de una clase desconocida en Perl
Respuesta
No realmente.
TL; DR:
Puede encontrar los nombres de subrutinas declarados o colocados en el espacio de nombres de clase del objeto de forma explícita.
Usted no puede distinguir cuál de estas subrutinas son métodos del objeto sobre el objeto y que son de clase o no a objetos submarinos (este es el problema más grave/limintation entre los enumerados).
NO puede encontrar los métodos heredados por un objeto en la subclase de la superclase usando este método, a menos que ya hayan sido invocados en su objeto.
Esto se puede codificar alrededor, inspeccionando
@ISA
de la clase a build up inheritance trees, or using on of proper CPAN modules.NO puede encontrar los métodos que se agregan dinámicamente a la clase (AUTOLOAD, la inyección manual de métodos en el código en alguna parte).
En detalle
Puede encontrar todas las subrutinas de esa clase (combinando el hecho de que el espacio de nombres de clases es un hash de modo que todos los identificadores en que son claves en ese resumen ; y la llamada
UNIVERSAL::can
para separar subrutinas).Por lo tanto, si está GARANTIZADO (mediante un contrato no técnico) que el 100% de las subrutinas en la clase son métodos de objetos Y que su clase NO es una subclase, puede encontrar su lista.
package MyClass; use vars qw($z5); my $x = 11; our $y = 12; $z5 = 14; %z2 = (1=>2); # my, our, globals, hash sub new { return bless({}, $_[0]) }; # Constructor sub x1 { my $self = shift; print $_[0]; }; sub y2 { my $self = shift; print $_[0]; }; ############################################################################## package MySubClass; use vars qw(@ISA); @ISA = ("MyClass"); sub z3 { return "" }; ############################################################################## package main; use strict; use warnings; my $obj = MyClass->new(); list_object_methods($obj); my $obj2 = MySubClass->new(); list_object_methods($obj2); $obj2->x1(); list_object_methods($obj2); # Add "x1" to the list! sub list_object_methods { my $obj = shift; my $class_name = ref($obj); no strict; my @identifiers = keys %{"${class_name}::"}; use strict; my @subroutines = grep { UNIVERSAL::can($obj, $_) } @identifiers; print "Class: ${class_name}\n"; print "Subroutines: \n=========\n" . join("\n", sort @subroutines) . "\n=========\n"; }
... impresiones:
Class: MyClass Subroutines: ========= new x1 y2 ========= Class: MySubClass Subroutines: ========= new z3 ========= Class: MySubClass Subroutines: ========= new x1 z3 =========
Tenga en cuenta que la lista por primera vez (por MySubClass) impreso
new
yz3
pero NOx1
y2
o - porquenew
fue ejecutado y fue declarado enz3
la clase; perox1
yy2
tampoco fueron - fueron teóricamente heredados. PERO, una vez que ejecutamos un métodox1
heredado, la segunda lista lo incluía, mientras que todavía faltaba ely2
heredado.pero no se puede, por desgracia, distinguir una subrutina que es un método de objeto (por ejemplo, trata el primer argumento se pone como un objeto), un método de clase (por ejemplo, trata el primer argumento se pone como una clase nombre) o un sub no OO (trata el primer argumento como argumento regular).
Para distinguir entre los 3, la ÚNICA forma es analizar semánticamente el código. De lo contrario, no se puede decir la diferencia entre:
sub s_print_obj { my ($self, $arg1) = @_; $s->{arg1} = $arg1; print "$arg1\n"; } # $obj->s_print_obj("XYZ") prints "XYZ" and stores the data in the object sub s_print_class { my ($class, $arg1) = @_; print "Class: $class\n"; print "$arg1\n"; } # $obj->s_print_class("XYZ") prints "Class: MyClass\nXYZ\n" sub s_print_static { my ($self, $arg1) = @_; print "$arg1\n"; } # $obj->s_print_static("XYZ") prints stringified representation of $obj
NOTA: Como cuestión de hecho, algunas personas realmente escriben los métodos de su clase - los que pueden trabajar de esta manera - para trabajar de forma explícita en todos los 3 (o primera 2) casos, no importa cómo se llame el método.
La respuesta de DVK es precisa, pero un poco larga. La respuesta breve es sí, puede, pero no sabrá qué se pretendía como método de objeto público y qué no. Los métodos privados y las funciones importadas de otros módulos pueden aparecer.
La forma más simple de obtener la lista de métodos invocables, concretos (es decir, no AUTOLOAD) es usar el método perl5i meta objectmethods().
use perl5i::2;
my $object = Something::Something->new;
my @methods = $object->mo->methods;
Eso al menos elimina una gran cantidad de código.
¿Cómo distinguen 'methods' entre los métodos del objeto y los subs no objeto de la clase (ver mis 3 ejemplos en la parte n. ° 2)? POD no parecía tener ninguna aclaración sobre eso. – DVK
Además, ¿se trata correctamente con cosas AUTOLOADed? – DVK
@DVK Simple: no es así. Como correctamente señaló, no puede. Simplemente enumera los métodos disponibles, concretos e invocables que hacen todo el recorrido de herencia y el examen de la tabla de símbolos para que no tenga que hacerlo. Corregiré algunos pronombres en mi respuesta para aclarar esto. * Podría * aprovechar la distinción func/método de perl5i, pero actualmente no lo hace. – Schwern
- 1. ¿Cómo repito todos los métodos de una clase en Perl?
- 2. Crear instancia de clase derivada de una instancia de clase base sin conocer los miembros de la clase
- 3. ¿Hay alguna manera de crear métodos solo para la instancia de una clase de Ruby desde esa instancia?
- 4. Serialización y restauración de una clase desconocida
- 5. Métodos de burla en cualquier instancia de una clase python
- 6. Métodos de instancia llamando a métodos de clase llamando a los métodos de instancia
- 7. ¿Cómo puedo redefinir los métodos de clase Perl?
- 8. ¿Hay alguna manera de conocer el método de invocación?
- 9. ¿Existe alguna manera hermosa de afirmar las condiciones previas en los métodos de Java?
- 10. ¿Hay alguna manera de precompilar una expresión regular en Perl?
- 11. ¿Hay alguna manera de desactivar la adición de propiedades a una clase desde una instancia de la clase?
- 12. ¿Existe alguna manera fácil de aleatorizar una lista en VB.NET?
- 13. ¿Hay alguna manera de decirle explícitamente a PyCharm qué clase es un atributo de una instancia?
- 14. ¿Puede una instancia de clase autodestruirse?
- 15. ¿Existe una manera sencilla de registrar los métodos que se invocan sobre un objeto en Ruby?
- 16. Los métodos de instancia en módulos
- 17. Serializar los métodos @property en una clase de Python
- 18. Listar todos los métodos de una clase dada, excluyendo los métodos de la clase padre en PHP
- 19. ¿Hay alguna manera de "extender" una clase en SASS?
- 20. Creación de una instancia de una clase C++ y métodos de llamada sobre ella en Python
- 21. ¿Existe alguna manera clara de asignar la clase de un tipo genérico a una variable?
- 22. ¿Existe alguna manera fácil de usar InternalsVisibleToAttribute?
- 23. ¿Existe alguna manera inteligente de pasar la clave a default_factory?
- 24. declarar una instancia de una clase const
- 25. ¿Hay alguna manera de anular automáticamente ToString() en una clase?
- 26. En Scala, ¿hay alguna manera fácil de convertir una clase de caso en una tupla?
- 27. Métodos de anulación de Java al crear una nueva instancia de una clase
- 28. ¿Existe una forma integrada de identificar instancias de una clase?
- 29. métodos especiales Anulación de una instancia
- 30. ¿Cómo dividir todos los métodos de una clase en GDB?
* "NO puede encontrar los métodos heredados por un objeto en la subclase de la superclase, a menos que ya hayan sido invocados en su objeto" *. Si le leo correctamente, ¿está diciendo que '$ obj-> inherited_method' debe ejecutarse antes de que pueda detectar' inherited_method'? No creo que sea cierto o [estas pruebas perl5i] (https://metacpan.org/source/MSCHWERN/perl5i-v2.9.1/t/Meta/methods.t) no funcionarían. ¿Tienes código para respaldar eso? – Schwern
@Schwern - vea la segunda oración en esa viñeta: "Esto puede codificarse, ya sea inspeccionando ISA de la clase para construir árboles de herencia, o usando los módulos de CPAN apropiados". La parte "Can NOT" se refería a la técnica resumida anteriormente de lectura directa del hash del espacio de nombres. El código de copia de seguridad de esta declaración (menos grandiouse de lo que lees) es mi código en la respuesta. – DVK
Oh. Acabo de tomar caminando '@ ISA' como algo dado. – Schwern