所以我正在学习Scala而且我遇到了这个棘手的问题......
如果我们有String
并希望将其转换为Int
,我在网上找到的所有示例都说:“这很简单!只需使用String.toInt
!”< / p>
好:
var x = readLine().toInt
足够简单。我假设toInt
是String
的函数。但如果是这样的话,我应该可以用括号来呼叫toInt
,对吧?来自Java,这对我来说更自然:
var x = readLine().toInt()
但是唉! Scala给了我以下错误:
[错误] /home/myhome/code/whatever/hello.scala:13:Int不采取 参数
[error] var x = readLine()。toInt()
好奇。这个错误是什么意思? toInt
不是String
的函数吗?同样,为什么我可以同时做到这两点:
var x = readLine().toLowerCase()
var y = readLine().toLowerCase
没有任何问题?
修改:重复的问题未解决toLowerCase
vs toInt
问题。
答案 0 :(得分:19)
这是一个很好的问题,我不认为它是带有或不带括号的question about defining zero-arity methods的副本。
此处toInt
和toLowerCase
之间的区别在于toInt
是由标准库StringOps
类提供的语法丰富。您可以使用REPL中的reify
和showCode
来检查:
scala> import scala.reflect.runtime.universe.{ reify, showCode }
import scala.reflect.runtime.universe.{reify, showCode}
scala> showCode(reify("1".toInt).tree)
res0: String = Predef.augmentString("1").toInt
这只是去除了浓缩方法调用,并向您展示了应用隐式转换来支持它。
如果我们查看toInt
method on StringOps
,我们会看到它的定义没有括号。正如可能重复问题的答案所指出的那样,如果Scala中的零度方法定义为没有括号,则不能用括号调用它(尽管如果它用括号定义,它可以被调用方式)。
这就是"1".toInt()
无效的原因。如果String
是遵循正常Scala命名约定的普通Scala类,则"ABC".toLowerCase()
也不会起作用,因为该方法将被定义为没有括号,因为它不会产生副作用(这只是一个约定,但它往往在Scala代码中非常一致地应用。)
问题是String
实际上并不是Scala标准库中的一个类 - 它只是java.lang.String
。在JVM级别,使用括号定义的零arity方法与没有括号定义的零方法之间没有区别 - 这纯粹是Scala的区别,并且它不是在JVM方法签名中编码,而是在存储在类文件中的单独一批元数据。
Scala语言设计人员决定处理Scala中未定义的所有零度方法(因此不具备此额外元数据),就好像它们是用括号定义的一样。由于toLowerCase
上的String
方法确实是java.lang.String
类的方法(不是像toInt
那样的句法丰富方法),因此它属于此类别,这意味着你可以用任何一种方式来称呼它。