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

标签 perl object

我在 Perl 中有一个程序,它使用我从另一个来源获得的包。该方法的功能之一返回一个未知类的对象,有没有办法让我在不查看其类实现的情况下获取对象的所有可能方法?

最佳答案

并不真地。

TL;DR:

  • 您可以找到显式声明或放置在对象类的 namespace 中的子例程的名称。
  • 您无法区分这些子例程中哪些是对象上的对象方法,哪些是类或非对象子程序 (这是列出的最严重的问题/限制)。
  • 使用此方法, 找不到子类中的对象从父类(super class)继承的方法。除非他们已经在你的对象上被调用了。

    这可以通过检查 @ISA 来编码。类(class)的build up inheritance trees, or using on of proper CPAN modules .
  • 您找不到动态添加到类中的方法(AUTOLOAD,在某处的代码中手动注入(inject)方法)。

  • 详细
  • 您可以找到该类中的所有子例程(通过结合类 namespace 是一个散列的事实,因此其中的所有标识符都是该散列中的键;以及对单独子例程的 UNIVERSAL::can 调用)。

    因此,如果您保证(通过非技术契约(Contract))类中 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";
    }
    

    ... 打印:
    Class: MyClass
    Subroutines:
    =========
    new
    x1
    y2
    =========
    Class: MySubClass
    Subroutines:
    =========
    new
    z3
    =========
    Class: MySubClass
    Subroutines:
    =========
    new
    x1
    z3
    =========
    

    请注意首次列表(针对 MySubClass)打印 newz3但不是 x1y2 - 因为new被处决和z3在类中声明;但是 x1y2两者都不是——它们只是理论上继承的。但是,一旦我们执行了继承的 x1方法,然后第二次列表包含它,但仍然缺少继承的 y2 .

  • 但不幸的是,您不能区分作为对象方法的子例程(例如,将其获得的第一个参数视为对象)、类方法(例如,将其获得的第一个参数视为类名)或非 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
    

    注意:事实上,有些人实际上编写了他们的类的方法——那些可以以这种方式工作的方法——明确地在所有 3 种(或前 2 种)情况下工作,无论该方法如何被调用。
  • 关于perl - 有没有办法知道 Perl 中未知类的实例的方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10869511/

    相关文章:

    string - 转换字符串中的字符

    CSS图像显示空白?

    perl - 如何从 Perl 使用 Active Directory?

    javascript - 如何在javascript对象中调用jquery事件?

    perl - mojolicious 禁用点占位符路由

    jquery - 这是如何在 JSON 中使用哈希值吗?

    javascript - 我如何将对象键名称指定为与其值相同的名称?

    javascript - 使用 Javascript 或 jQuery 将数组字符串转换为对象

    ios - 在一个紧密的循环中读取或写入 NSUserDefaults 是不是很糟糕?

    Python 使用字符串名称访问现有变量