Impilcits

In Scala, you can add new functionality to closed classes by writing implicit conversions and bringing them into scope when you need them. A major benefit of this approach is that you don’t have to extend existing classes to add the new functionality. Note that you can define as many methods as you need in your implicit class.

Implicit conversion works as follows - the compiler first tries to compile it as is, but it sees a type error. Before giving up, it looks for an implicit conversion that can repair the problem. Implicit definitions are those that the compiler is allowed to insert into a program in order to fix any of its type errors.

For example, if x + y does not type check, then the compiler might change it to convert(x) + y, where convert is some available implicit conversion. If convert changes x into something that has a + method, then this change might fix a program so that it type checks and runs correctly.

Rules of Implicit conversions

Marking Rule: Only definitions marked implicit are available. The implicit keyword is used to mark which declarations the compiler may use as implicits.

Scope Rule: An inserted implicit conversion must be in scope as a single identifier, or be associated with the source or target type of the conversion. The Scala compiler will only consider implicit conversions that are in scope. To make an implicit conversion available, therefore, you must in some way bring it into scope. Moreover, with one exception, the implicit conversion must be in scope as a single identifier. Исключением из этого правила является то, что все неявные преобразования неявно импортируются из объекта-компаньона (ассоциированные преобразования). The Scope Rule helps with modular reasoning. When you read code in a file, the only things you need to consider from other files are those that are either imported or are explicitly referenced through a fully qualified name.

One-at-a-time Rule: Only one implicit is tried. The compiler will never rewrite x + y to convert1(convert2(x)) + y. Doing so would cause compile times to increase dramatically on erroneous code, and it would increase the difference between what the programmer writes and what the program actually does. For sanity’s sake, the compiler does not insert further implicit conversions when it is already in the middle of trying another implicit. Если было применено одно неявное преобразование, второе не применяется.

Explicits-First Rule: Whenever code type checks as it is written, no implicits are attempted. The compiler will not change code that already works. A corollary of this rule is that you can always replace implicit identifiers by explicit ones, thus making the code longer but with less apparent ambiguity. Если нет ошибок, и все проверки типов прошли успешно, неявные преобразования не применяются.

Naming an implicit conversion. Implicit conversions can have arbitrary names. The name of an implicit conversion matters only in two situations: if you want to write it explicitly in a method application, and for determining which implicit conversions are available at any place in the program. In this example, it was important that the implicit conversions had names, because only that way could you selectively import one and not the other.

Where implicits are tried. There are three places implicits are used in the language: (1) conversions to an expected type, (2) conversions of the receiver of a selection, (2) and implicit parameters.

  • Implicit conversions to an expected type let you use one type in a context where a different type is expected

  • Conversions of the receiver let you adapt the receiver of a method call, i.e., the object on which a method is invoked, if the method is not applicable on the original type. Например, использование стрелочки -> на любом объекте позволяет.

  • Implicit parameters, on the other hand, are usually used to provide more information to the called function about what the caller wants. Implicit parameters are especially useful with generic functions, where the called function might otherwise know nothing at all about the type of one or more arguments. To let the compiler supply the parameter implicitly, you must first define a variable of the expected type with implicit modifier. Если implicit применяется к списку параметров, то оно применяется ко всем параметрам в этом списке.

Application rule. If one of the available conversions is strictly more specific than the others, then the compiler will choose the more specific one. To be more precise, one implicit conversion is more specific than another if one of the following applies:

  • The argument type of the former is a subtype of the latter’s.

  • Both conversions are methods, and the enclosing class of the former extends the enclosing class of the latter.

Last updated