其他编程语言上的魔术方法

问题描述 投票:-3回答:2

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

[我尝试使用谷歌搜索“其他编程语言中的魔术方法”,但未显示任何相关内容,可能它们在不同语言中使用不同的名称。

language-agnostic magic-methods
2个回答
4
投票

[通常,一种语言的“魔术”过多表示语言设计不良。也许这就是为什么很少有使用魔术方法的语言的原因?

像这样的魔术创建了一个两类系统:语言设计者可以向该语言添加新的魔术方法,但是程序员只能使用大祭司语言设计允许的方法。通常,程序员应该尽可能多地执行[[without要求更改语言规范。

例如,在Scala中,+-*/==!=<><=>=,[C0 ],::|&||&&**^+=-=*=等,依此类推只是合法标识符。因此,如果要为自己的对象实现自己的乘法版本,只需编写一个名为/=的方法。这只是一种无聊的旧标准方法,绝对没有“魔术”。

相反,

any

方法可以使用运算符表示,即不带点。而且,只需采用一个参数的任何方法都可以在运算符表示法中不加括号地调用。这不仅适用于方法。同样,任何带有两个类型实参的类型构造函数都可以用中缀表示法使用,因此如果我有

*

我可以做

class ↔️[A, B]

与]相同>

class Foo extends (String ↔️ Int)

嗯……我撒谎:Scala中有一些语法糖:

如果范围内没有名为class Foo extends ↔️[String, Int] 的方法,则将

    foo()转换为foo.apply()。这使您可以有效地重载函数调用运算符。
  • foo转换为foo.bar = baz。这使您可以有效地重载属性分配。 (这是您在Scala中编写二传手的方法。)
  • foo.bar_=(baz)转换为foo(bar) = baz。这使您可以有效地重载索引分配。 (例如,这就是在Scala中编写数组或字典访问的方式。)>
  • [foo.update(bar, baz)(和其他几个)被翻译为!foo
  • foo.unary_!将尝试调用foo += bar+=方法,即,它等效于foo。但是,如果此操作失败
  • and
  • foo.+=(bar)是有效的左值,and foo具有一个名为foo的方法,那么Scala也会尝试使用+
此外,优先级,关联性和固定性在Scala中是固定的:它们由方法名称的第一个字符确定。即所有以foo = foo + bar开头的方法都具有相同的优先级,所有以*开头的方法都具有相同的优先级,依此类推。

Haskell更进一步:功能和运算符之间没有

根本区别。每个函数都可以用在函数调用符号和运算符符号中。唯一的区别是词法:如果函数名称由运算符组成,那么当我想在函数调用符号中使用它时,必须将其用括号括起来。 OTOH,如果函数名称由字母数字字符组成,并且我想在运算符符号中使用它,则需要将其包装在反引号中。因此,以下是等效的:

-
对于操作员使用功能,您可以自由定义固定性,关联性和优先级,例如:

a + b (+) a b a `plus` b plus a b

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

infixr 15 <!==!>

def +(other) plus(other) end C++是您要寻找的。

[operator overloading不支持运算符重载(Java)。

Reference没有运算符重载(C)。因此,写入了许多Referenceadd等功能。这些宏通常是宏,因为它们可以用于不同的类型。恕我直言,这就是为什么我更喜欢C ++的原因。

@ Alex给mult简要介绍了操作员重叠。


2
投票
def +(other) plus(other) end C++是您要寻找的。

-4
投票
这些在python中称为

Dunder Methods

© www.soinside.com 2019 - 2024. All rights reserved.