uzl*_*xxx 10 javascript python oop inheritance raku
每当您在 JavaScript 或 Python 中扩展类时,派生类都必须使用super
关键字才能设置属性和/或调用基类中的方法和构造函数。例如:
class Rectangle {
constructor(length, width) {
this.name = "Rectangle";
this.length = length;
this.width = width;
}
shoutArea() {
console.log(
`I AM A ${this.name.toUpperCase()} AND MY AREA IS ${this.length * this.width}`
);
}
rectHello() {
return "Rectanglish: hello";
}
}
class Square extends Rectangle {
constructor(length) {
super(length, length);
this.name = "Square"
}
squaHello() {
const h = super.rectHello();
return "Squarish:" + h.split(':')[1];
}
}
const rect = new Rectangle(6, 4);
rect.shoutArea(); //=> I AM A RECTANGLE AND MY AREA IS 24
const squa = new Square(5);
squa.shoutArea(); //=> I AM A SQUARE AND MY AREA IS 25
console.log(squa.squaHello()); //=> Squarish: hello
Run Code Online (Sandbox Code Playgroud)
rai*_*iph 11
\n\nJavaScript 和 Python 中使用的关键字在Raku 中的等价物是什么
\nsuper
?
Raku 的重调度功能之一.\xc2\xb9
\n首先是一些不包含重新调度函数的代码:
\nclass Rectangle {\n has ($.length, $.width)\n}\n\nRectangle.new: length => 6, width => 4;\n
Run Code Online (Sandbox Code Playgroud)\n该Rectangle
声明甚至不包含构造代码,仅包含两个属性的声明,仅此而已。
那么这个Rectangle.new
电话在做什么呢?它继承了new
Raku 类提供的默认方法Mu
,该方法初始化名称与任何命名参数匹配的任何类属性。
如果您想要一个接受位置参数的自定义构造函数,那么您通常会编写一个new
方法,在其签名中列出您想要的参数,然后让该方法调用new
通过调用适当的重新调度函数来适当地调用 default ,这需要命名参数参数转换为命名参数:
class Rectangle {\n has ($.length, $.width);\n method new ($length, $width) { callwith length => $length, width => $width }\n}\n\nRectangle.new: 6, 4;\n
Run Code Online (Sandbox Code Playgroud)\ncallwith
是一个重新调度函数,它执行以下操作:
基于原始调用调用下一个匹配候选者。\xc2\xb2
\n并提出了一系列新的论点。
\n在这个简单的例子中,原始调用是Rectangle.new: 6, 4
,下一个候选是new
从 继承的方法Mu
。
Rectangle
基于您的课程我不会模仿你的代码,而是编写一个惯用的 Raku 翻译并对其进行评论。
\nclass Rectangle {\n has ($!length, $!width) is required is built;\n method new ($length, $width) { callwith :$length, :$width }\n method shoutArea { put uc "I am a {self.^name} and my area is {$!length * $!width}" }\n method rectHello { \'Rectanglish: hello\' }\n}\n\nconstant rect = Rectangle.new: 6, 4;\nrect.shoutArea; #=> I AM A RECTANGLE AND MY AREA IS 24\n
Run Code Online (Sandbox Code Playgroud)\n评论:
\n默认编写代码可以限制随着代码的发展可能出现的问题,这是一个好习惯。因此,我使用了$!length
length 属性而不是$.length
.\xc2\xb3
我已经is required
为属性添加了注释。这意味着在实例构造结束时未能初始化属性将意味着抛出异常。
我已经is built
为属性添加了注释。这意味着,即使没有公共访问器的属性(正如我在“twigil”中使用$!length
而不是使用的情况一样),如果构造调用中存在匹配的命名参数,仍然可以/将自动初始化。$!width
!
.
:$length
是 的缩写length => $length
。
self.^name
避免不必要的开销。这并不重要,而且阅读起来很可能会分散注意力,所以请随意忽略我解释它的脚注。\xe2\x81\xb4
Square
基于您的课程我将进行new
重新Square
调度:
class Square is Rectangle {\n method new ($side-length) { callwith $side-length, $side-length }\n method squaHello { "Squarish: {self.rectHello.split(\':\')[1].trim}" }\n}\n\nconstant squa = Square.new: 5;\nsqua.shoutArea; #=> I AM A SQUARE AND MY AREA IS 25\nput squa.squaHello; #=> Squarish: hello\n
Run Code Online (Sandbox Code Playgroud)\n评论:
\n$side-length
我为Square
参数选择了名称.new
,但名称并不重要,因为它是位置参数/参数。
抽象地说,重新分派是给下一个候选人的,就像以前一样。具体来说,这次的下一个候选者是我刚刚定义的方法Rectangle
(它又重新分派到new
of Mu
)。
self.rectHello
就足够了,因为被调用的方法与最初调用的方法 ( squaHello
) 具有不同的名称。Rectangle
如果您将和中的两个方法重命名Square
为具有相同的名称Hello
,那么重新调度将再次是合适的,尽管这次我写的只是而callsame
不是callwith ...
因为callsame
只是使用原始中提供的相同参数重新调度到下一个候选者调用,这将省去再次写出参数的麻烦。
\xc2\xb9 重新调度是诸如super
. 重新调度函数有多种用途,包括与面向对象无关的用途。
\xc2\xb2 在 Raku 中,函数或方法调用可能会导致编译器生成可能匹配候选者的列表,同时考虑诸如方法调用的调用者以及函数和方法的多个调度和函数包装器等因素。构建了候选列表后,它会分派给领先的候选者(或者在重新分派给下一个候选者的情况下,分派给下一个候选者)。
\n\xc2\xb3 如果您确实希望为给定属性自动生成 getter/setter,请使用.
, 例如$.length
代替 来声明它$!length
,Raku 将同时生成$!length
属性和.length
getter。is rw
(如果您在声明中添加 an ,那么还有一个设置器$.length
。)我在第一个代码示例中这样做是为了让事情变得更简单。
\xe2\x81\xb4^
方法调用中的 likefoo.^bar
意味着方法调用被“向上”bar
重定向(因此是)^
到高阶工作对象,该对象知道如何作为特定类型发挥作用。在本例中,a是一个类,HOW对象是 的一个实例,它知道类如何工作,包括每个类都有一个不同的名称,并且有一个检索该名称的方法。类的名称当然是“矩形”,因此不必使用类的名称创建其他内容。foo
Rectangle
Perl6::Metamodel::ClassHOW
.name
Rectangle
self.^name
归档时间: |
|
查看次数: |
356 次 |
最近记录: |