【问题标题】:Overloading operators for a class类的重载运算符
【发布时间】:2019-09-12 19:23:10
【问题描述】:

假设我有以下课程:

class A {
    has $.val;

    method Str { $!val ~ 'µ'  }  
}

# Is this the right way of doing it?
multi infix:<~>(A:D $lhs, A:D $rhs) {
    ('(', $lhs.val, ',', $rhs.val, ')', 'µ').join;
}

如何以与上一个类中的Str 相同的方式为一个类重载一个运算符(例如,+)?

我猜这仅适用于在实例对象上调用的方法,并且对运算符使用 multi operator-type:&lt;OP&gt;(T $lhs, T $rhs) { } 语法是正确的方法,但我不确定。

例如,在 Python 中,以运算符命名的特殊方法(例如 operator.__add__)和运算符(例如 +)之间似乎存在对应关系。此外,自定义类的任何运算符重载都是在类内部完成的。

【问题讨论】:

    标签: operator-overloading raku


    【解决方案1】:

    在 Perl 6 中,运算符被视为当前语言的一部分。与当前语言相关的所有事物都是按词法定义的(即my-scoped)。因此,multi sub 是正确的使用方法。

    如果将此代码放入模块中,您可能还希望使用is export 标记运算符的multi

    multi infix:<~>(A:D $lhs, A:D $rhs) is export {
        ('(', $lhs.val, ',', $rhs.val, ')', 'µ').join;
    }
    

    以便useimport 模块的用户可以使用它(use 实际上是根据import 定义的,import 将符号导入词法范围)。

    虽然有些运算符默认委托给方法(例如,prefix:&lt;+&gt; 调用 Numeric),但两者之间没有 1:1 的关系,并且对于大多数运算符而言,它们的实现直接在运算符 @987654333 中实现@(或分布在多个 multi subs 上)。

    此外,运算符集是开放的,因此不限于重载现有运算符,还可以引入新的运算符。当操作符的新含义与所用符号的正常语义没有明显相关时,这是鼓励的;例如,重载+ 来进行矩阵加法是明智的,但对于不可能被视为一种加法的东西,新的运算符会是更好的选择。

    【讨论】:

    • “虽然有些运算符默认委托给方法(例如,前缀: 调用 Numeric),但两者之间没有 1:1 的关系,...”。这清楚了很多。谢谢!
    【解决方案2】:
    class A {
        has $.val;
    
        method Str { $!val ~ 'µ'  }
    }
    
    multi infix:<~>(A:D $lhs, A:D $rhs) {
        ('(', $lhs.val, ',', $rhs.val, ')', 'µ').join;
    }
    
    dd A.new(val => "A") ~ A.new(val  => "B"); # "(A,B)µ"
    

    所以是的,这是正确的方法。如果要覆盖+,则要创建的子名称为infix:&lt;+&gt;

    您还可以通过使用:U“类型笑脸”为类型对象提供案例,例如:

    multi infix:<~>(A:U $lhs, A:U $rhs) {
        'µ'
    }
    

    希望这能回答你的问题。

    【讨论】:

    • 当然可以!我担心我做得不好,或者至少,像比我更有经验的人通常那样做:-)!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-06-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-29
    • 1970-01-01
    • 2015-11-19
    • 1970-01-01
    相关资源
    最近更新 更多