Действительно ли я могу получить доступ к статическому методу в динамично указанном классе в Perl?

Используйте asp:Panel для этого. Это переводит в отделение

10
задан Sinan Ünür 27 October 2009 в 23:08
поделиться

5 ответов

Ага! Чтобы сделать это с помощью ограничений, используйте can .

package Foo::Bar;
use strict;
use warnings;

sub baz
{
   return "Passed in '@_' and ran baz!";
}

package main;
use strict;
use warnings;

my $class = 'Foo::Bar';

if (my $method = $class->can('baz'))
{
   print "yup it can, and it ";
   print $method->();
}
else
{
   print "No it can't!";
}

can возвращает ссылку на метод undef / false. Затем вам просто нужно вызвать метод с синтаксисом разыменования.

Он дает:

    > perl foobar.pl
    yup it can, and it Passed in '' and ran baz!
10
ответ дан 3 December 2019 в 18:34
поделиться

Как всегда с Perl, есть несколько способов сделать это .

use strict;
use warnings;
{
  package Test::Class;
  sub static_method{ print join(' ', @_), "\n" }
}
  • Вы можете использовать специальную переменную % :: для доступ к таблице символов.

     my $ class = 'Test :: Class';
    мой @depth = split '::', $ class;
    
    мой $ ref = \% ::;
    $ ref = $ glob -> {$ _. '::'} для @depth; # $ :: {'Test ::'} {'Class ::'}
    
    $ code = $ glob -> {'static_method'};
    $ code -> ('Привет', 'Мир');
    
  • Вы можете просто использовать символическую ссылку ;

     без строгих ссылок;
    мой $ code = & {"$ {class} :: static_method"};
    # или
    мой $ code = * {"$ {class} :: static_method"} {CODE};
    $ code -> ('Привет', 'Мир');
    
  • Вы также можете использовать строку eval .

     eval "$ {class} :: static_method ('Hello', 'World')";
    
  • Самым простым в этом случае было бы использовать UNIVERSAL :: can .

     $ code = $ class-> can ('static_method');
    $ code -> ('Привет', 'Мир');
    
5
ответ дан 3 December 2019 в 18:34
поделиться

Я не знаю особенно хорошего способа сделать это, но есть и менее приятные способы, такие как эта программа :

#!/usr/bin/perl -w

use strict;

package Test::Class1;

sub static_method {
  print join(", ", @_) . "\n";
}

package main;

my $class = "Test::Class1";

{
  no strict "refs";
  &{${class}. "::static_method"}(1, 2, 3);
}

Я добавил переменную $ class , поскольку именно так вы задали вопрос, и она показывает, как имя класса может быть выбрано во время выполнения, но если вы знаете класс заранее, вы можете так же легко вызовите & {"Test :: Class1 :: static_method"} (1, 2, 3);

Обратите внимание, что вы должны отключить строгие "ссылки" , если у вас есть это дальше.

4
ответ дан 3 December 2019 в 18:34
поделиться

Вы можете использовать строку eval :

#!/usr/bin/perl

use strict; use warnings;

package Test::Class1;

sub static_method {
  print join(", ", @_) . "\n";
}

package main;

my $class = 'Test::Class1';
my $static_method = 'static_method';

my $subref = eval q{ \&{ "${class}::${static_method}" } };
$subref->(1, 2, 3);

Вывод:

C:\Temp> z
1, 2, 3

Тесты:

#!/usr/bin/perl

use strict; use warnings;

package Test::Class1;

sub static_method { "@_" }

package main;

use strict; use warnings;
use Benchmark qw( cmpthese );

my $class = 'Test::Class1';
my $static_method = 'static_method';

cmpthese -1, {
    'can' => sub { my $r = $class->can($static_method); $r->(1, 2, 3) },
    'eval' => sub {
        my $r = eval q/ \&{ "${class}::${static_method}" } /;
        $r->(1, 2, 3);
    },
    'nostrict' => sub {
        no strict "refs";
        my $r = \&{ "${class}::static_method" };
        $r->(1, 2, 3);
    }
};

Вывод:

             Rate     eval      can nostrict
eval      12775/s       --     -94%     -95%
can      206355/s    1515%       --     -15%
nostrict 241889/s    1793%      17%       --
1
ответ дан 3 December 2019 в 18:34
поделиться

Есть три основных способа вызвать статическую функцию:

  • $ object-> static_method ()
  • Classname-> static_method ()
  • Classname :: static_method ()

Вы можете определить свою функцию так:

# callable as $object->static_method() or Classname->static_method()
sub static_method
{
    my $class = shift;    # ignore; not needed
    # ...
}

или подобным этому, которая работает во всех трех сценариях вызова и не работает » t несут какие-либо накладные расходы на вызывающей стороне, как это делает решение Роберта П.:

use UNIVERSAL qw(isa);

sub static_method
{
    my $class = shift if $_[0] and isa($_[0], __PACKAGE__);
    # ...
}
1
ответ дан 3 December 2019 в 18:34
поделиться
Другие вопросы по тегам:

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