其他编程语言的魔术方法

Magic methods on other programming languages

Python有__add____mul____cmp__等方法(称为magic methods),作为class 方法,并且可以赋予不同的含义以添加 (+)、乘法 (*)、比较 (==)、... class 的两个实例.我的问题是其他语言有类似的方法吗?我熟悉 Java、C++、ruby 和 PHP,但从未遇到过这样的事情。我知道这四个都有一个对应于 __init__ 的构造函数方法,但是其他魔术方法呢?

我尝试使用谷歌搜索 "Magic methods in other programming languages" 但没有找到任何相关信息,可能它们在不同语言上的名称不同。

C++ operator overloading 中是您要查找的内容。

Java 不支持运算符重载 (Reference)。

C 没有运算符重载 (Reference)。于是,写了一大堆addmult等等函数。通常那些是宏,因为它们可以用于不同的类型。恕我直言,这就是我更喜欢 C++ 的原因。

@Alex reference 很好地概述了运算符覆盖。

一般来说,一种语言中 "magic" 过多是语言设计不良的标志。也许这就是为什么没有很多语言有魔术方法?

这样的魔法创建了一个双class系统:语言设计者可以为语言添加新的魔法方法,但程序员只能使用语言设计大祭司允许的方法到。一般来说,程序员应该可以做到尽可能多的而不需要改变语言规范。

例如,在 Scala 中,+-*/==!=<><=>=::|&||&& , **, ^, +=, -=, *=, /=, 等等,都是合法的标识符。因此,如果您想为自己的对象实现自己的乘法版本,只需编写一个名为 * 的方法即可。这只是一个无聊的旧标准方法,绝对没有什么"magic"。

相反,any 方法可以使用运算符符号调用,即不带点。任何只接受一个参数的方法都可以在运算符符号中不带括号地调用。

这不仅适用于方法。此外,任何具有两个类型参数的类型构造函数都可以在中缀表示法中使用,所以如果我有

class ↔️[A, B]

我可以

class Foo extends (String ↔️ Int)

相同
class Foo extends ↔️[String, Int]

好吧……我有点撒谎了:Scala 中有一些语法糖:

    如果范围内没有名为 foo 的方法,
  • foo() 将转换为 foo.apply()。这允许您有效地重载函数调用运算符。
  • foo.bar = baz 被翻译成 foo.bar_=(baz)。这允许您有效地重载 属性 赋值。 (这就是您在 Scala 中编写 setter 的方式。)
  • foo(bar) = baz 被翻译成 foo.update(bar, baz)。这允许您有效地重载索引分配。 (例如,这就是您在 Scala 中编写数组或字典访问的方式)。
  • !foo(和其他几个)被翻译成 foo.unary_!.
  • foo += bar会尝试调用foo+=方法,即等价于foo.+=(bar)。但是如果失败 and foo 是一个有效的左值,and foo 有一个名为 + 的方法,那么 Scala 也会尝试 foo = foo + bar 而不是

此外,优先级、结合性和固定性在 Scala 中是固定的:它们由方法名称的第一个字符决定。 IE。所有以 * 开头的方法具有相同的优先级,所有以 - 开头的方法具有相同的优先级,依此类推。

Haskell 更进一步:函数和运算符之间没有基本 区别。每个函数都可以用在函数调用符号和运算符符号中。唯一的区别是词法上的:如果函数名由运算符字符组成,那么当我想在函数调用符号中使用它时,我必须将它括在括号中。 OTOH,如果函数名称由字母数字字符组成并且我想在运算符符号中使用它,我需要将它用反引号括起来。所以,以下是等价的:

a + b
(+) a b

a `plus` b
plus a b

对于函数的运算符用法,可以自由定义固定性、结合性、优先级,例如:

infixr 15 <!==!>

在Ruby中有一组预定义的运算符,有相应的方法,例如:

def +(other)
  plus(other)
end