初学者Scala问题,但我在这里找不到答案。
与C ++中的重载类似,我希望编译器可以区分一个名为-
的方法,它带有一个参数(与类相同的类型)和一元版本的-
它没有参数,为什么需要unary_
?
答案 0 :(得分:69)
一元前缀运算符的unary_
前缀有点误导:它比一元部分更多地关于前缀部分。你需要一些方法来区分
!foo // unary prefix !
来自
foo! // unary postfix !
请记住:Scala实际上没有运营商。调用方法有两种方法,使用.
或使用空格:
foo.bar(1, "two")
foo bar(1, "two")
当你有一个参数时,你可以不用括号:
foo plus(1)
foo plus 1
最后,(几乎)任何字符在标识符中是合法的:
foo plus 1
foo + 1
现在它看起来就像Scala有一个二进制中缀+
运算符,但它实际上没有。它只是用普通方法调用语法调用的普通方法。
然而,我上面所说的并不是完全。如果Scala不支持运算符,那么这只是普通的方法调用,那么
2 + 3 * 4
将评估为20(例如,在Smalltalk,Self和Newspeak中),而不是14.因此,在Scala中有一个 little 位支持运算符(实际上是两个小位,实际上) )。当使用空格(所谓的“运算符语法”)而不是.
调用方法时,该方法以运算符字符开头,则Scala将尊重运算符优先级。
另外一点运算符支持是有一些你喜欢的运算符,但这不能很容易地表示为方法调用。它适用于二进制中缀运算符和一元后缀运算符:
foo op bar // same as:
foo.op(bar)
foo op // same as:
foo.op
但不是前缀或“around-fix”运算符:
!foo
foo(bar)
因此,有一些特殊的语法糖转换规则:
!foo
foo.unary_!
// same for +, - and ~
foo(bar)
foo.apply(bar)
foo(bar) = 1
foo.update(bar, 1)
foo += 1
foo.+=(1) // but if this doesn't compile, then the compiler will also try
foo = foo.+(1)
并且在方法名称中需要在字母数字和“运算符”部分之间加下划线的原因是因为您不知道是否
foo!
表示
foo.!
或
this.foo!
因此,foo!
作为方法名称是非法的,需要将其称为foo_!
。
答案 1 :(得分:9)
因为在scala中创建一个名为-
的方法是完全没问题的,所以它不带参数。你如何区分普通方法和一元方法?例如,!
与一元修复操作符具有完全不同的含义。