Как я могу проверить, определен ли метод в классе Perl 6?

Я часто хочу проверить, что я определил метод конкретного класса. Это поймало много проблем, когда я переименовал метод или иным образом переставил вещи в архитектуре.

Я знаю, что могу использовать .^lookup но это все еще кажется мне странным, как будто я в конечном итоге столкнусь с случаем, когда он возвращает вещи в другом порядке, чем я ожидаю (игнорировать подписи сейчас). Вот что я придумал:--4-->

use Test;

class Foo is Str {}
class Bar is Str { method Str { 'Hello' } }

can-ok Str, 'Str';
can-ok Foo, 'Str';
can-ok Bar, 'Str';

is Foo.^lookup( 'Str' ).package.^name, 'Foo', 'Foo defines Str';
is Bar.^lookup( 'Str' ).package.^name, 'Bar', 'Bar defines Str';

done-testing;

Я не хочу в этом простом случае и до сих пор я не дал ему провалиться:

ok 1 - The type 'Str' can do the method 'Str'
ok 2 - The type 'Foo' can do the method 'Str'
ok 3 - The type 'Bar' can do the method 'Str'
not ok 4 -
ok 5 -
1..5
# Failed test at /Users/brian/Desktop/hello.p6 line 12
# expected: 'Foo'
#      got: 'Mu'
# Looks like you failed 1 test of 5

1 ответов


вы не должны сравнивать типы по имя.

my \Foo = anon class Foo {}
my \Bar = anon class Foo {}

say Foo.^name eq  Bar.^name; # True
say Foo       eqv Bar;       # False

в самом деле is проверка на тождество объекта, если вы даете ему объект типа в качестве второго аргумента.

is Bar.^lookup( 'Str' ).package, Bar, 'Bar defines Str'

вы всегда можете добавить подпрограмму, чтобы добавить ясность.

sub defines-method (
  Mu:U $class,
  Str:D $method,
  Str:D $desc = "$class.^name() defines $method"
) {
  is $class.^lookup( $method ).?package, $class, $desc
}

defines-method Foo, 'Str';

вы можете псевдоним его оператору

sub &infix:<defines-method> = &defines-method;

Bar defines-method 'Str';

(обратите внимание, что я использовал .?package в случае .^lookup ничего не вернуть.)


.^lookup дает вам метод объект, который будет вызван; поэтому я не знаю, почему вы говорите об этом, давая вам их в другом порядке, когда возвращается только одно значение. Если есть несколько методов, он возвращает метод proto (возможно, неявно созданный).
Если вы хотите отдельные методы multi, вы бы назвали .candidates на нем.
(Существует также .^find_method, и с моей головы я не помню разницы)

я думаю, вы думаете о .can что дает вам объекты метода в том порядке, в котором они будут вызываться, если вы использовали .*Str или .+Str, что совпадает с порядком разрешения метода. Это означает, что он изменится, только если вы измените дерево наследования.

> class Bar is Str { method Str { 'Hello' } }

> quietly .perl.say for Bar.+Str;
"Hello"
""
""

> .perl.say for Bar.new.+Str
"Hello"
""
"Bar<80122504>"

> quietly .(Bar).perl.say for Bar.can('Str')
"Hello"
""
""

> .(Bar.new).perl.say for Bar.can('Str')
"Hello"
""
"Bar<86744200>"