JavaScript 和 Python 中使用的 super 关键字在 Raku 中的等价物是什么?

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

JavaScript 和 Python 中使用的关键字在Raku 中的等价物是什么super

\n
\n

Raku 的重调度功能之一.\xc2\xb9

\n

重新调度的基础知识

\n

首先是一些不包含重新调度函数的代码:

\n
class Rectangle {\n  has ($.length, $.width)\n}\n\nRectangle.new: length => 6, width => 4;\n
Run Code Online (Sandbox Code Playgroud)\n

Rectangle声明甚至不包含构造代码,仅包含两个属性的声明,仅此而已。

\n

那么这个Rectangle.new电话在做什么呢?它继承了newRaku 类提供的默认方法Mu,该方法初始化名称与任何命名参数匹配的任何类属性。

\n
\n

如果您想要一个接受位置参数的自定义构造函数,那么您通常会编写一个new方法,在其签名中列出您想要的参数,然后让该方法调用new通过调用适当的重新调度函数来适当地调用 default ,这需要命名参数参数转换为命名参数:

\n
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)\n

callwith是一个重新调度函数,它执行以下操作:

\n
    \n
  • 基于原始调用调用下一个匹配候选者。\xc2\xb2

    \n
  • \n
  • 并提出了一系列新的论点。

    \n
  • \n
\n

在这个简单的例子中,原始调用是Rectangle.new: 6, 4,下一个候选是new从 继承的方法Mu

\n

Rectangle基于您的课程

\n

我不会模仿你的代码,而是编写一个惯用的 Raku 翻译并对其进行评论。

\n
class 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
    \n
  • 默认编写代码可以限制随着代码的发展可能出现的问题,这是一个好习惯。因此,我使用了$!lengthlength 属性而不是$.length.\xc2\xb3

    \n
  • \n
  • 我已经is required为属性添加了注释。这意味着在实例构造结束时未能初始化属性将意味着抛出异常。

    \n
  • \n
  • 我已经is built为属性添加了注释。这意味着,即使没有公共访问器的属性(正如我在“twigil”中使用$!length而不是使用的情况一样),如果构造调用中存在匹配的命名参数,仍然可以/将自动初始化。$!width!.

    \n
  • \n
  • :$length是 的缩写length => $length

    \n
  • \n
  • self.^name避免不必要的开销。这并不重要,而且阅读起来很可能会分散注意力,所以请随意忽略我解释它的脚注。\xe2\x81\xb4

    \n
  • \n
\n

Square基于您的课程

\n

我将进行new重新Square调度:

\n
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
    \n
  • $side-length我为Square参数选择了名称.new,但名称并不重要,因为它是位置参数/参数。

    \n
  • \n
  • 抽象地说,重新分派是给下一个候选人的,就像以前一样。具体来说,这次的下一个候选者是我刚刚定义的方法Rectangle(它又重新分派到newof Mu)。

    \n
  • \n
  • self.rectHello就足够了,因为被调用的方法与最初调用的方法 ( squaHello) 具有不同的名称。Rectangle如果您将和中的两个方法重命名Square为具有相同的名称Hello,那么重新调度将再次是合适的,尽管这次我写的只是而callsame不是callwith ...因为callsame只是使用原始中提供的相同参数重新调度到下一个候选者调用,这将省去再次写出参数的麻烦。

    \n
  • \n
\n

脚注

\n

\xc2\xb9 重新调度是诸如super. 重新调度函数有多种用途,包括与面向对象无关的用途。

\n

\xc2\xb2 在 Raku 中,函数或方法调用可能会导致编译器生成可能匹配候选者的列表,同时考虑诸如方法调用的调用者以及函数和方法的多个调度和函数包装器等因素。构建了候选列表后,它会分派给领先的候选者(或者在重新分派给下一个候选者的情况下,分派给下一个候选者)。

\n

\xc2\xb3 如果您确实希望为给定属性自动生成 getter/setter,请使用., 例如$.length代替 来声明它$!length,Raku 将同时生成$!length属性和.lengthgetter。is rw(如果您在声明中添加 an ,那么还有一个设置器$.length。)我在第一个代码示例中这样做是为了让事情变得更简单。

\n

\xe2\x81\xb4^方法调用中的 likefoo.^bar意味着方法调用被向上”bar重定向(因此是^高阶工作对象,该对象知道如何作为特定类型发挥作用。在本例中,a是一个HOW对象是 的一个实例,它知道类如何工作,包括每个类都有一个不同的名称,并且有一个检索该名称的方法。类的名称当然是“矩形”,因此不必使用类的名称创建其他内容。fooRectanglePerl6::Metamodel::ClassHOW.nameRectangleself.^name

\n