perl - 是否可以获得特定 Perl 类的所有有效方法?

标签 perl class oop methods

是否可以获得特定 Perl 类的所有有效方法?

我正在尝试操作一个类的符号表并获取它的所有方法。我发现我可以通过 $obj->can($method) 将子程序与非子程序分开。 ,但这并不完全符合我的想法。

以下返回:

subroutine, Property, croak, Group, confess, carp, File

但是,subroutine不是一种方法,(只是一个子程序)和croak , confess , 和 carp都导入到我的包中。

我真正想打印的是:
Property,Group, File

但我会采取:
subroutine, Property,Group, File

下面是我的程序:
#! /usr/bin/env perl

use strict;
use warnings;
use feature qw(say);

my $sections = Section_group->new;
say join ", ", $sections->Sections;

package Section_group;
use Carp;

sub new     {
    return bless {}, shift;
}

sub Add {
    my $self                = shift;
    my $section             = shift;
}

sub Sections {
    my $self                = shift;

    my @sections;
    for my $symbol ( keys %Section_group:: ) {
        next if $symbol eq "new";   # This is a constructor
        next if $symbol eq "Add";   # Not interested in this method
        next if $symbol eq "Sections";      # This is it's own method
        push @sections, $symbol if $self->can($symbol);
    }

    return wantarray ? @sections : \@sections;
}

sub subroutine {
    my $param1              = shift;
    my $param2              = shift;
}

sub Group {
    my $self                = shift;
    my $section             = shift;
}

sub File {
    my $self                = shift;
    my $section             = shift;
}

sub Property {
    my $self                = shift;
    my $section             = shift;
}

最佳答案

这是相当微不足道的。我们只想保留那些最初在我们的包中定义的子名称。每个 CV(代码值)都有一个指向定义它的包的指针。感谢 B ,我们可以检查:

use B ();

...

if (my $coderef = $self->can($symbol)) {
  my $cv = B::svref_2object $coderef;
  push @sections, $symbol if $cv->STASH->NAME eq __PACKAGE__;
}

# Output as wanted

也就是说,我们使用 svref_2object 执行自省(introspection)。 .这将返回一个表示内部 perl 数据结构的 Perl 对象。

如果我们查看 coderef,我们会得到 B::CV object ,代表内部CV . STASH CV 中的字段指向定义它的 Stash。如您所知,一个 Stash 只是一个特殊的哈希(内部表示为 HV ),所以 $cv->STASH返回 B::HV . NAME HV 的字段如果 HV 是 Stash,而不是常规哈希,则包含 Stash 的完全限定包名称。

现在我们有了我们需要的所有信息,并且可以将想要的包名称与 coderef 的存储名称进行比较。

当然,这是简化的,您将希望通过 @ISA 进行递归。普通类。

没有人喜欢被污染的命名空间。值得庆幸的是,有些模块可以从 Stash 中删除外来符号,例如namespace::clean .当您调用的所有子程序的 CV 在编译时已知时,这没有问题。

关于perl - 是否可以获得特定 Perl 类的所有有效方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18390256/

相关文章:

perl - 解析/分解 - 一步步解释这个混淆的 perl 脚本

java - 为什么 java.lang.Object 不是抽象的?

Python 方法调用

带有初始值设定项的 C++ 匿名类

java - 如何限制子类修改抽象类中方法的范围?

oop - 形容词的接口(interface)命名

java - 从 UTF-8 base64 编码识别日语

Perl:修剪多行记录

perl - Perl的 map 有什么意义?

javascript - 将点击事件绑定(bind)到类中的方法