在JavaScript和Python中使用的关键字super
的Raku对应值是什么?
拉库re-dispatching functions人中的一人.
Basics of redispatch
首先,Do not的一些代码包括重新调度功能:
class Rectangle {
has ($.length, $.width)
}
Rectangle.new: length => 6, width => 4;
Rectangle
声明甚至不包括构造代码,只有两个属性的声明,仅此而已.
那么,Rectangle.new
呼叫在做什么呢?它继承了Raku的Mu
类提供的默认new
方法,该方法初始化名称与任何命名参数匹配的任何类属性.
如果您想要一个接受positional个参数的自定义构造函数,则通常编写一个new
方法,其中列出您希望在其签名中包含哪些参数,然后让该方法调用需要命名参数的默认new
,方法是调用一个适当的重调度函数,将参数转换为命名参数:
class Rectangle {
has ($.length, $.width);
method new ($length, $width) { callwith length => $length, width => $width }
}
Rectangle.new: 6, 4;
callwith
是重调度功能,它执行以下操作:
基于原始呼叫的下一个匹配候选者的call%
with一组新的论点.
在这个简单的例子中,最初的调用是Rectangle.new: 6, 4
,下一个候选方法是从Mu
继承的new
方法.
A Rectangle
class based on yours
我不会模仿您的代码,而是编写一个惯用的Raku翻译并对其进行注释.
class Rectangle {
has ($!length, $!width) is required is built;
method new ($length, $width) { callwith :$length, :$width }
method shoutArea { put uc "I am a {self.^name} and my area is {$!length * $!width}" }
method rectHello { 'Rectanglish: hello' }
}
constant rect = Rectangle.new: 6, 4;
rect.shoutArea; #=> I AM A RECTANGLE AND MY AREA IS 24
comments :
默认编写代码来限制代码演变过程中可能出现的问题是一个好习惯.出于这个原因,我使用了$!length
作为长度属性,而不是$.length
.
我已经为属性添加了is required
注释.这意味着在实例构造结束时未能初始化属性将意味着抛出异常.
我已经为属性添加了is built
注释.这意味着,即使没有公共访问器的属性--就像$!length
和$!width
的情况一样,因为我使用的是!
而不是"twigil"中的.
--如果构造调用中有匹配的命名参数,它仍然可以/仍然会被自动初始化.
:$length
是length => $length
的缩写.
self.^name
可避免不必要的开销.阅读这篇文章并不重要,而且很可能会让人分心,所以你可以忽略我的脚注来解释它.⁴
A Square
class based on yours
我会用new
比Square
重新调度:
class Square is Rectangle {
method new ($side-length) { callwith $side-length, $side-length }
method squaHello { "Squarish: {self.rectHello.split(':')[1].trim}" }
}
constant squa = Square.new: 5;
squa.shoutArea; #=> I AM A SQUARE AND MY AREA IS 25
put squa.squaHello; #=> Squarish: hello
comments :
我为Square
‘S .new
参数 Select 了名称$side-length
,但名称并不重要,因为它是位置参数/实参.
抽象地说,重新调度是给下一位候选人的,就像以前一样.具体地说,这一次的下一个候选方法是我刚才在Rectangle
中定义的方法(它又重新调度到Mu
的new
).
self.rectHello
就足够了,因为被调用的方法与最初调用的方法(squaHello
)具有不同的名称.如果将Rectangle
和Square
中的两个方法重命名为具有相同的名称Hello
,那么重新分派也是合适的,尽管这一次我只编写了callsame
而不是callwith ...
,因为callsame
只是使用原始调用中提供的相同参数重新分派给下一个候选项,这将省go 再次写出参数的麻烦.
Footnotes
?重新调度是对super
等功能的概括.重调度函数用于一系列目的,包括与面向对象无关的目的.
?在RAKU中,函数或方法调用可能会导致编译器生成一个可能匹配的候选对象列表,考虑的因素包括方法调用的调用以及函数和方法的多个分派和函数包装.在构建了候选人列表之后,它然后将其分派给领先的候选人(或者在重新分派给下一个候选人的情况下是下一个).
³如果你真的想为一个给定的属性自动生成一个getter/setter,那么用一个.
来声明它,例如$.length
而不是$!length
,Raku会同时生成一个$!length
属性和一个.length
getter.(如果您在$.length
声明中添加is rw
,也是一个setter.)我在第一个代码示例中这样做是为了让事情更简单一些.
在像foo.^bar
这样的方法调用中⁴^
意味着bar
方法调用被"向上"(因此是^
)重定向到知道foo
如何作为一种特定类型工作的H更高的OrderW排序对象.在本例中,Rectangle
是class,而HOW对象是Perl6::Metamodel::ClassHOW
的实例,它知道类是如何工作的,包括每个类具有不同的name,并且具有检索该名称的.name
方法.当然,Rectangle
类的名称是‘Rectangle’,因此self.^name
省go 了用类的名称创建其他东西的麻烦.