2017-02-18 59 views
15

Так я учусь Scala, и я наткнулся на этот вопрос привередлив ...Scala Строка toInt - Int не принимает параметры

Если у нас есть String и хотят, чтобы преобразовать его в Int, все примеры, которые я «Я нашел онлайн-ответ:« Это так просто! Просто используйте String.toInt! »

Хорошо:

var x = readLine().toInt 

достаточно просто. Я предполагаю, что toInt является функцией String. Но если это так, я должен был бы позвонить toInt с круглыми скобками, верно? Исходя из Java, мне это кажется более естественным:

var x = readLine().toInt() 

Но, увы! Scala дает мне следующую ошибку:

[error] /home/myhome/code/whatever/hello.scala:13: Int does not take parameters

[error] var x = readLine().toInt()

Любопытный. Что означает эта ошибка? Is toInt не является функцией String? Аналогичным образом, почему я могу сделать оба:

var x = readLine().toLowerCase() 
var y = readLine().toLowerCase 

без каких-либо проблем?

Редактировать: Повторяющийся вопрос не касается вопроса toLowerCase vs toInt.

+0

Возможный дубликат [В чем разница между def foo = {} и def foo() = {} в Scala?] (Http://stackoverflow.com/questions/7409502/what-is-the-difference- между-def-foo-and-def-foo-in-scala) –

ответ

19

Это хороший вопрос, и я не думаю, что он считается дубликатом question about defining zero-arity methods с круглыми скобками или без них.

Разница между toInt и toLowerCase здесь является то, что toInt является синтаксическим обогащение, StringOps класса из стандартной библиотеки. Вы можете проверить это с помощью 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 

Это просто desugars вызов метода обогащения и показывает, что неявное преобразование было применено, чтобы поддержать его.

Если мы посмотрим на toInt method on StringOps, мы увидим, что он определен без круглых скобок. Поскольку ответ на возможный дублирующий вопрос указывает на то, что если метод нулевой аргумента в Scala определен без круглых скобок, его нельзя вызывать с круглыми скобками (хотя, если он определен в круглых скобках, он может быть вызван в любом случае).

Так вот почему "1".toInt() не работает. Если String были обычным классом Scala, следующим нормальным соглашениям об именах Scala, "ABC".toLowerCase() тоже не работал, поскольку метод был бы определен без круглых скобок, поскольку он не является побочным эффектом (это просто соглашение, но оно, как правило, довольно последовательно применяется в коде Scala).

Проблема в том, что String на самом деле не класс в стандартной библиотеке Scala - это всего лишь java.lang.String. На уровне JVM нет никакой разницы между методом с нулевой степенью, определенным с круглыми скобками, и одним без круглых скобок - это чисто различие Scala, и оно не кодируется в сигнатуре метода JVM, а в отдельной партии метаданных, хранящихся в файл класса.

Дизайнеры языка Scala решили обработать все методы нулевого уровня, которые не определены в Scala (и, следовательно, не имеют этих дополнительных метаданных), как если бы они были определены с круглыми скобками. Поскольку метод toLowerCase на String действительно и действительно является методом класса java.lang.String (а не синтаксического метода обогащения, такого как toInt), он попадает в эту категорию, что означает, что вы можете назвать его в любом случае.

+0

Спасибо за ваш ответ. Таким образом, чтобы устранить пробел в моем понимании, метод с нулевой артерией - это метод, который определяется без круглых скобок, и это только по соглашению (т. Е. Я могу определить метод, который не принимает аргументов с круглыми скобками, чтобы сделать его более похожим на Java)? Таким образом, я бы назвал метод с нулевым уровнем, как будто я обращался к полю? И если я использую Java-классы/библиотеки, нет таких методов, как методы ноль-арности? Кроме того, что такое «побочный эффект»? –

+0

@KennethWorden Я использую «zero-arity» для ссылки на любой метод, который не принимает аргументы, независимо от того, определяется ли он скобками или без них. В Java есть методы, которые не принимают аргументы (и считаются нулевыми в этом смысле), но не делают различий между их определениями с круглыми скобками или нет (как вопрос синтаксиса Java, все они). –

+0

И «побочное действие» здесь означает, что это не функция в математическом смысле - она ​​может печатать что-то, возвращать разные значения при последующих вызовах и т. Д. –