Ich habe versucht zu verstehen, wie implizite Parameter in Scala funktionieren. So weit ich weiß, geht die implizite Parameterauflösung ungefähr so:Lazy Vals und implizite Parameter in Scala
- Explizites Übergeben eines Objekts an die Methode.
- implizite Definitionen im Geltungsbereich definiert.
- Companion Objekt der Klasse als impliziten Parameter
jedoch verwendet, wenn ich mit diesem in Verbindung faul vals Herumspielen begonnen habe ich ein bisschen ein supprise. Es scheint, dass Lazy Vals nur die letzten Auflösungsregeln verwenden. Hier finden Sie einige Codebeispiele veranschaulichen:
class Bar(val name:String)
object Bar { implicit def bar = new Bar("some default bar") }
class Foo {
lazy val list = initialize
def initialize(implicit f:Bar) = {
println("initialize called with Bar: '" + f.name + "' ...")
List[Int]()
}
}
trait NonDefaultBar extends Foo {
implicit def f = new Bar("mixed in implicit bar")
def mixedInInit = initialize
lazy val mixedInList = list
}
object Test {
def test = {
println("Case 1: with implicitp parameter from companion object")
val foo1 = new Foo
foo1.list
foo1.initialize
println("Case 2: with mixedin implicit parameter overriding the default one...")
val foo2 = new Foo with NonDefaultBar
foo2.mixedInList
val foo3 = new Foo with NonDefaultBar
foo3.mixedInInit
println("Case 3: with local implicit parameter overriding the default one...")
implicit def nonDefaultBar = new Bar("locally scoped implicit bar")
val foo4 = new Foo
foo4.list
foo4.initialize
}
}
Aufruf Test.test
gibt die folgende Ausgabe:
Case 1: with implicitp parameter from companion object
initialize called with Bar: 'some default bar' ...
initialize called with Bar: 'some default bar' ...
Case 2: with mixedin implicit parameter overriding the default one...
initialize called with Bar: 'some default bar' ...
initialize called with Bar: 'mixed in implicit bar'...
Case 3: with local implicit parameter overriding the default one...
initialize called with Bar: 'some default bar' ...
initialize called with Bar: 'locally scoped implicit bar' ...
Warum der Compiler nicht fängt, dass es eine implict Bar ist gemischt beim Aufruf mixedInList in Fall 2. In Fall 3 fehlt auch der lokal definierte implizite Balken beim Zugriff auf die Liste.
Gibt es Möglichkeiten, implizite Parameter mit Lazy Vals zu verwenden, die das im Begleitobjekt definierte implizite Parameter nicht verwenden?
Ok, aber * sollte nicht * es die implicits erkennen? Sie sind bei Compiletime bekannt, richtig? Vielleicht würde es funktionieren, wenn ich den impliziten Parameter zum Konstruktor verschiebe? –
Es erkennt den einzigen impliziten Balken, der zum Zeitpunkt der Kompilierung im Gültigkeitsbereich ist, und das ist der im Bar-Begleiter. Da 'list' nur auf' Foo' definiert ist, wird immer dieses verwendet. Sie könnten das implizite in Ihrem Konstruktor definieren, aber das implizite in dem Merkmal wäre immer noch nicht im Gültigkeitsbereich, da es nur für die Instanz existiert. – drexin
Also, wenn ich die Methode lazy val und initialize auf das 'NonDefaultBar'-Merkmal verschiebe und dieses Merkmal' Foo' erweitern lasse und auch das implizite def nach 'Foo' verschiebe, dann würde ich den Compiler das implizite def in' Foo greifen 'bei der Auswertung der' Lazy Val List'? –