如何测试Perl 6类中是否定义了方法?

bri*_*foy 6 testing perl6

我经常想测试我在特定类中定义了一个方法.这已经解决了许多问题,我已经重命名了一个方法或者重新安排了架构中的东西.

我知道我可以使用,.^lookup但这对我来说仍然感觉很奇怪,因为我最终会遇到一个案例,它以不同的顺序返回事物(暂时忽略签名).这就是我想出的:

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;
Run Code Online (Sandbox Code Playgroud)

它在我这个简单的例子中做了我想做的事情,到目前为止我没有让它失败:

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
Run Code Online (Sandbox Code Playgroud)

Bra*_*ert 7

您不应该按名称比较类型.

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

say Foo.^name eq  Bar.^name; # True
say Foo       eqv Bar;       # False
Run Code Online (Sandbox Code Playgroud)

实际上is,如果给它一个类型对象作为第二个参数,则检查对象标识.

is Bar.^lookup( 'Str' ).package, Bar, 'Bar defines Str'
Run Code Online (Sandbox Code Playgroud)

您可以随时添加子例程以增加清晰度.

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';
Run Code Online (Sandbox Code Playgroud)

您可以将其别名为运营商

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

Bar defines-method 'Str';
Run Code Online (Sandbox Code Playgroud)

(注意我用过.?package的情况下.^lookup不会返回任何内容.)


.^lookup为您提供将被调用的Method对象; 所以我不知道为什么你在谈论它只返回一个值时以不同的顺序给你.如果有多种方法,则返回proto方法(可能隐式创建).
如果你想要单独的多种方法,你可以调用.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>"
Run Code Online (Sandbox Code Playgroud)