Die Spezifikation behandelt die Überladungsauflösung als Disambiguierung einer Auswahl von Mitgliedern einer Klasse. Aber die implizite Auflösung verwendet die statische Überladungsauflösung, um zwischen Referenzen zu wählen, die keine Mitglieder sind.
Argumentieren, die folgende ist eine Fehlinterpretation der Spezifikation, da zzz
in einer Klasse von X
viel wie yyy
abgeleitet definiert ist:
$ scala
Welcome to Scala 2.12.0 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_101).
Type in expressions for evaluation. Or try :help.
scala> import concurrent._, ExecutionContext.global
import concurrent._
import ExecutionContext.global
scala> trait X { implicit val xxx: ExecutionContext = global }
defined trait X
scala> class Y extends X { implicit val yyy: ExecutionContext = global ; def f = implicitly[ExecutionContext] }
defined class Y
scala> class Z extends X { def f(implicit zzz: ExecutionContext) = implicitly[ExecutionContext] }
<console>:16: error: ambiguous implicit values:
both value xxx in trait X of type => scala.concurrent.ExecutionContext
and value zzz of type scala.concurrent.ExecutionContext
match expected type scala.concurrent.ExecutionContext
class Z extends X { def f(implicit zzz: ExecutionContext) = implicitly[ExecutionContext] }
^
Derzeit müssen Sie auf die Benennung verlassen, um die impliziten von umschließenden beschatten Umfang:
scala> class Z extends X { def f(implicit xxx: ExecutionContext) = implicitly[ExecutionContext] }
defined class Z
Oder
scala> :pa
// Entering paste mode (ctrl-D to finish)
package object p { import concurrent._ ; implicit val xxx: ExecutionContext = ExecutionContext.global }
package p { import concurrent._ ;
class P { def f(implicit xxx: ExecutionContext) = implicitly[ExecutionContext]
def g = implicitly[ExecutionContext] }
}
// Exiting paste mode, now interpreting.
scala>
Das entsprechende Commit im Scala/Scala Repo ist https://github.com/scala/scala/commit/44953dcb08fc5dd92e423a56bd42bcc32757aaef und die Begründung für die Änderung ist https://issues.scala-lang.org/browse/SI-8849 –
Viktor Klang kommentiert das JIRA-Ticket: "empfehlen, ExecutionContext.global entweder explizit zu übergeben oder ihr eigenes implizites val einzufügen, wenn nötig" –
Wenn ich das Problem richtig verstanden habe, funktioniert es in 2.11 tatsächlich "falsch" oder sehr am wenigsten unerwartet, da das "global" über das implizite im scope ausgewählt wird? Und 2.12 entlarvt diesen möglichen Programmierfehler, indem er ihn mehrdeutig macht. Erwähnenswert wäre dies in den Release Notes und/oder in der Dokumentation. – ochrons