当我创建一个以^
开头的类方法并尝试调用它时,它给我一个错误。
class C {
method ^test () {
"Hi"
}
}
dd C.new.test;
Too many positionals passed; expected 1 argument but got 2
in method test at .code.tio line 1
in block <unit> at .code.tio line 1
如果我使用相同的方法而不使用前导^
,则效果很好。
class C {
method test () {
"Hi"
}
}
dd C.new.test;
"Hi"
我已经看到模块使用以^
开头的方法公开类,这引发了我的问题。定义以^
开头的方法名称时,为什么会出现此错误?
答案 0 :(得分:8)
TL; DR 该方法正在正确调用。 ^
中的foo.^bar
表示“元方法”。这既不是实例方法也不是类方法。像所有方法一样,元方法既传递给调用者,也传递和另一个“原始调用者”对象作为第一个参数。
大多数用户将永远不需要考虑这些东西。但是您已经问过,所以让我们深入...
引用Meta-object protocol (MOP) P6文档页面:
Perl 6构建在元对象层上。
此MOP层定义了各种可以使用的内置“元方法”。
例如:
say .^attributes given class bar { has Int $!foo }
这将显示(Int $!foo)
。 .^attributes
方法调用是一种元方法。在(通常是不可见的)元对象上调用它,该元对象确定P6类型在幕后的工作方式。在这种情况下,它将返回类的属性(has
变量)。
但是也可以有用户定义的元方法。声明它们的一种方法是在其他普通类中:
say .^attributes given class baz { has Int $!foo; method ^attributes ($arg) { self, $arg } }
上面的baz
类包含一个^attributes
元方法声明,该声明覆盖了内置的元方法。需要特别说明的是,我添加了一个参数。所有元方法(至少有一个常规倡导者)都至少有一个论点。
使用此声明,而不是通过(Int $!foo)
来响应.^attributes
调用,您可以从self, $arg
类中的.^attributes
方法获取列表baz
请注意,self
既不是baz
实例对象也不是baz
类型的对象-而是Perl6::Metamodel::ClassHOW+{<anon>}.new
-而$arg
是一个baz
(类型)对象。
此答案的其余部分将更详细地说明正在发生的事情。
首先,让我们回顾一下典型的方法调用。
语法foo.bar
导致将“栏”方法(消息)发送到foo
。
如果foo
是一个类的实例,则将“ bar”调度到该实例。有时将这种方法调用称为“实例方法”。
如果foo
是对应于一个类的type object,则“ bar”被分派到该类型对象。有时将这种方法调用称为“类方法”。
在这两种情况下,“ bar”都分派到foo
。
foo.^bar
语法foo.^bar
不同。
将^
指向指向另一个悬在foo
上方的物体,或者与foo
类型的种类有关的任何物体。< / p>
此类对象是HOW
对象,它们确定对象的工作方式。这些HOW
对象通常保持不可见,使工作正常,用户非常高兴地不知道它们的存在及其正在做的工作。 1
形式为foo.^bar
的方法调用通常会导致P6向foo
的{{1}}对象分配元方法调用。
这些元方法需要两个倡导者般的论点。有HOW
对象。这作为常规倡导者通过。然后是HOW
对象。这作为第一个普通参数传递给元方法。
这就是调用foo
时通常发生的情况–元方法调用被分派到foo.^bar
的{{1}}对象,并且foo
作为普通参数存储传递可以说是“原始的煽动者”。
HOW
元方法时foo
如果在没有这种方法的情况下调用foo.^bar
,则会收到错误消息:
.^bar
产量:
foo.^bar
请注意,发起人类型是元模型类,而不是42.^bar
或No such method 'bar' for invocant of type 'Perl6::Metamodel::ClassHOW'
。
如果用户定义的类声明了42
,则P6调用它,将实例/类的Int
对象作为主诉者,将“原始参与者”(^.bar
)作为主旨。第一个普通论点:
HOW
1 在对象上调用foo
返回其class foo {
method ^bar ($arg) { self, $arg }
}
say foo.^bar; # (Perl6::Metamodel::ClassHOW+{<anon>}.new (foo))
:
.HOW
HOW
对象是MOP(位于P6内部的一层)的一部分。
大多数开发人员都不需要显式地深入到这一层次。
如果您进行更深入的挖掘,则将保留指定的P6。在Rakudo中,say .HOW given class {} # Perl6::Metamodel::ClassHOW
对象的HOW
通常是NQP对象:
.HOW