ORM может быть медленнее, но это компенсируется их способностью кешировать данные, поэтому, как бы быстро ни была альтернатива, вы не можете получить намного быстрее, чем чтение из памяти.
Рекомендация, которую дал Тодд Гарднер использовать 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.
Вы можете легко получить список определенных методов класса, используя уже предоставленные ответы. Однако 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 );
}
В общем случае, вам нужно будет проверить таблицу символов (если вы не используете Moose). Например, чтобы перечислить методы, определенные в пакете IO :: File
:
Зависит от того, имеете ли вы в виду любой класс или реализуете ли вы свой собственный. Для последнего я использую 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
Возможно, вам нужны методы Class :: Inspector-> ('Your :: Class').
Сказал Нафф.