Как я циклично выполняюсь по всем методам класса в Perl?

ORM может быть медленнее, но это компенсируется их способностью кешировать данные, поэтому, как бы быстро ни была альтернатива, вы не можете получить намного быстрее, чем чтение из памяти.

9
задан brian d foy 21 June 2009 в 12:42
поделиться

5 ответов

Рекомендация, которую дал Тодд Гарднер использовать Moose, хорошая, но выбранный им пример кода не очень полезен.

Если вы проверяете класс, использующий не Moose, вы бы сделали что-то вроде этого:

use Some::Class;
use Class::MOP;

my $meta = Class::MOP::Class->initialize('Some::Class');

for my $meth ( $meta->get_all_methods ) {
    print $meth->fully_qualified_name, "\n";
}

См. Class :: MOP :: Class docs для получения более подробной информации о том, как проводить интроспекцию.

Вы также заметите, что я использовал Class :: MOP вместо Moose. Class :: MOP (MOP = Meta-Object Protocol) - это основа, на которой строится Moose. Если вы работаете с классами, отличными от Moose, использование Moose для интроспекции ничего вам не даст.

Если хотите, вы можете использовать Moose () и Moose :: Meta: : Class-> инициализировать вместо CMOP.

13
ответ дан 4 December 2019 в 06:49
поделиться

Вы можете легко получить список определенных методов класса, используя уже предоставленные ответы. Однако Perl - это динамический язык, что означает, что позже может быть определено больше методов. На самом деле нет способа получить список всех методов, с которыми будет работать какой-либо конкретный класс. Для более подробного ознакомления с подобными вещами у меня есть несколько глав в Освоение Perl .

Люди дают вам (и голосуют за) ответы, не сообщая вам об ограничениях.

Адам упоминает его Class :: Inspector , но на самом деле он не работает, потому что он пытается сделать то, что не делает динамический язык (и это статично :) Например, вот фрагмент, где Class :: Inspector не возвращает методов, но я все еще могу вызвать метод VERSION (а также isa и can ):

    BEGIN {

package Foo;

our $VERSION = '1.23'
}

use Class::Inspector;

my $methods = Class::Inspector->methods( 'Foo' );

print "Methods are [@$methods]\n"; # reports nothing

print Foo->VERSION, "\n";

Вот еще один случай, когда я могу вызвать любой метод, который мне нравится, но Class :: Inspector возвращает только AUTOLOAD (и все еще отсутствует VERSION , isa и can ):

BEGIN {

package Foo;

our $VERSION = '1.23';

my $object = bless {}, __PACKAGE__;

sub AUTOLOAD { $object }

}

use Class::Inspector;

my $methods = Class::Inspector->methods( 'Foo' );

print "Methods are [@$methods]\n"; # reports only "AUTOLOAD"

print Foo->dog->cat->bird, "\n";

Любопытно, что все похоже, игнорирует UNIVERSAL, вероятно, потому, что они явно не обрабатывают его, поскольку он только виртуально в @ISA. Я могу добавить метод debug к каждому классу, и Class :: Inspector по-прежнему пропускает его, хотя это определенный метод:

BEGIN {

sub UNIVERSAL::debug { "Hello debugger!\n" }    
package Foo;
}

use Class::Inspector;

my $methods = Class::Inspector->methods( 'Foo' );

print "Methods are [@$methods]\n"; # still reports nothing

print Foo->debug, "\n";

Class :: MOP имеет те же ограничения.

Нет. каждый модуль будет использовать AUTOLOAD, но это тоже не таинственная или редкая функция. Если вы не возражаете, что вы пропустите некоторые методы, тогда Class :: Inspector или Class :: MOP могут подойти. Он просто не даст вам список всех методов, которые вы можете вызывать для класса или объекта в каждом случае.

Если у вас есть класс или объект, и вы хотите знать, можете ли вы вызвать конкретный метод, используйте жестяная банка(). Оберните его в блок eval, чтобы можно было вызывать can () для вещей, которые даже не являются объектами, чтобы в таких случаях вернуть false вместо смерти:

if( eval { $object->can( 'method_name' ) } )
    {
    $object->( @args );
    }
10
ответ дан 4 December 2019 в 06:49
поделиться

В общем случае, вам нужно будет проверить таблицу символов (если вы не используете Moose). Например, чтобы перечислить методы, определенные в пакете IO :: File :

5
ответ дан 4 December 2019 в 06:49
поделиться

Зависит от того, имеете ли вы в виду любой класс или реализуете ли вы свой собственный. Для последнего я использую Moose , который предлагает очень чистый синтаксис для этих функций. Из поваренной книги:

my %attributes = %{ $self->meta->get_attribute_map };
for my $name ( sort keys %attributes ) {
   my $attribute = $attributes{$name};

   if (   $attribute->does('MyApp::Meta::Attribute::Trait::Labeled')
   # ... keeps on
3
ответ дан 4 December 2019 в 06:49
поделиться

Возможно, вам нужны методы Class :: Inspector-> ('Your :: Class').

Сказал Нафф.

3
ответ дан 4 December 2019 в 06:49
поделиться
Другие вопросы по тегам:

Похожие вопросы: