有没有办法知道Perl中未知类的实例的方法

SIM*_*MEL 5 perl object

我在Perl中有一个程序,它使用我从其他来源获得的包.该方法的一个函数返回一个未知类的对象,有没有办法让我获得一个对象的所有可能方法,而无需查看它的类实现?

DVK*_*DVK 9

并不是的.

TL; DR:

  • 您可以找到显式声明或放入对象类的命名空间的子例程的名称.

  • 您无法区分哪些子例程是对象上的对象方法,哪些是类或非对象子(这是列出的最严重的问题/限制).

  • 除非已在对象上调用它们,否则您无法使用此方法找到超类中子对象继承的方法.

    这可以通过检查@ISA类来构建继承树或使用适当的CPAN模块来编码.

  • 您无法找到动态添加到类中的方法(AUTOLOAD,代码中的手动方法注入).

详细地

  1. 您可以在该类中找到所有子例程(通过组合类命名空间是哈希的事实,因此其中的所有标识符都是该哈希中的键;以及UNIVERSAL::can对单独子例程的调用).

    因此,如果您(通过非技术合同)保证类中100%的子例程是对象方法,并且您的类不是子类,则可以找到它们的列表.

    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";
    }
    
    Run Code Online (Sandbox Code Playgroud)

    ...打印:

    Class: MyClass
    Subroutines:
    =========
    new
    x1
    y2
    =========
    Class: MySubClass
    Subroutines:
    =========
    new
    z3
    =========
    Class: MySubClass
    Subroutines:
    =========
    new
    x1
    z3
    =========
    
    Run Code Online (Sandbox Code Playgroud)

    请注意,第一次列表(MySubClass)印刷newz3,但不x1还是y2-因为new被执行,并z3在课堂上被宣布; 但x1y2既不是-他们仅仅是理论上的继承.但是,一旦我们执行了一个继承的x1方法,那么第二次列表就会包含它,但仍然缺少继承的方法y2.


  2. 但遗憾的是,您不能区分作为对象方法的子例程(例如,将它作为对象获取的第一个参数),类方法(例如将其作为类名称获取的第一个参数)或非OO子元素区分开来. (将第一个参数视为常规参数).

    为了区分3,唯一的方法是实际上在语义上分析代码.否则,你无法区分:

    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
    
    Run Code Online (Sandbox Code Playgroud)

    注意:事实上,有些人实际上写了他们的类的方法 - 那些可以这样工作的方法 - 明确地工作在ALL 3(或前2)的情况下,无论方法如何被调用.