Как работает «20 секунд» в Scala?


130

Как компилируется следующее:

import scala.concurrent.duration._

val time = 20 seconds

Что на самом деле здесь происходит?

Ответы:


171

Происходит несколько вещей.

Во-первых, Scala позволяет опускать точки и скобки во многих вызовах методов, что 20 secondsэквивалентно 20.seconds()*.

Во-вторых, применяется «неявное преобразование». Так как 20это Intи Intне имеет никакого secondsметода, компилятор ищет неявное преобразование , который принимает Intи возвращает то , что действительно есть в secondsметоде, с поиском стесненного рамкой вашего вызова метода.

Вы импортировали DurationInt в свою область видимости. Поскольку DurationIntэто неявный класс с Intпараметром, его конструктор определяет неявное Int => DurationIntпреобразование. DurationIntимеет secondsметод, поэтому он удовлетворяет всем критериям поиска. Поэтому компилятор переписывает ваш вызов как new DurationInt(20).seconds**.

* Я имею в виду это свободно. 20.seconds()фактически недействителен, потому что у secondsметода нет списка параметров, и поэтому скобки при вызове метода должны быть опущены.

** На самом деле это не совсем так, потому что DurationIntэто класс значений, поэтому компилятор по возможности избегает обертывания целого числа.


83
Любая достаточно развитая технология неотличима от магии.
ripper234

4
К счастью, большинство IDE могут это распознать! Неявные преобразования довольно часто используются в Scala. Если вы просто читаете текстовый файл, это может сбить с толку («откуда взялся этот метод»), но при соответствующей поддержке инструментов вы сможете сориентироваться, и в этот момент Scala может быть красиво осмысленным и кратким. (например, 20 секунд гораздо более читабельны, чем new DurationInt(20).seconds()до тех пор, пока вы знаете, как они это делают)
Уильям Биллингсли

1
Если вы обнаружите, что используете имплициты, всегда спрашивайте себя, есть ли способ добиться того же без их помощи. twitter.github.com/effectivescala/#Types and Generics-Implicits
oluies

4
На самом деле secondsметод определяется без скобок, поэтому вызов его с скобками является ошибкой.
Фрэнк С. Томас

1
@Frank Это хороший момент. Я не имел в виду, что вы можете писать 20.seconds()на Scala, я просто хотел сказать , что компилятор переводит вызов таким образом. Стоит отметить, что Scala требует , чтобы вы опускали скобки, если соответствующий метод не имеет списка параметров, как в этом случае.
Аарон Новструп

7

«Магия», которая там происходит, называется «неявным преобразованием». Вы импортируете неявные преобразования, и некоторые из них обрабатывают преобразование между Int (и Double) в Duration. Вот с чем вы имеете дело.


1
Есть идеи, почему импорт import scala.concurrent.duration._разрешает, 20 secondsа на самом деле импорт DurationConversionsTrait - нет? РЕДАКТИРОВАТЬ : только что понял, что они на самом деле импортируют DurationInt. Я предполагаю, что это потому, что вы не можете импортировать настоящую черту? Только конкретная реализация Черты?
Франклин
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.