Как я могу проверить, определен ли метод в классе 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>"