Warum funktioniert diese strukturelle Art nicht wie erwartet?
-
24-10-2019 - |
Frage
Ich versuche, eine einfache Helfermethode zu schreiben, die etwas empfängt, das geschlossen werden kann, und eine Funktion, die die erstere empfängt und sicherstellt, dass der "Schließbare" nach Ausführung der Funktion geschlossen ist.
Zum Beispiel möchte ich es so verwenden:
closing(new FileOutputStream("/asda"))(_.write("asas"))
Mein Impl ist
object Helpers {
def closing[T <: { def close }](closeable: T)(action: T => Unit): Unit =
try action apply closeable finally closeable close
}
Aber wenn Sie versuchen, diesen einfachen Test zu kompilieren:
object Test {
import Helpers._
closing(new FileOutputStream("/asda"))(_.write("asas"))
}
Der Compiler beschwert sich mit:
Abgeleitete Typargumente [java.io.FileOutputStream] entsprechen nicht den Typ -Parametergrenzen von Methodenschließungen [t <: mynessref {Def schließen: Einheit}
Irgendwelche Ideen warum?
Lösung
Sie müssen schreiben
def closing[T <: { def close() }]
Es gibt einen Unterschied in der Skala zwischen Methoden mit leeren Klammern und Methoden ohne Klammern.
Andere Tipps
Typgrenzen sind schwierig. Insbesondere verfolgt Scala die Anzahl der Parameterlisten zusätzlich zu den Parametern selbst. Probieren Sie diese aus!
class A { def f = 5 }
class B { def f() = 5 }
class C { def f()() = 5 }
def useA[X <: { def f: Int }](x: X) = x.f
def useB[X <: { def f(): Int }](x: X) = x.f
def useC[X <: { def f()(): Int}](x: X) = x.f
useA(new A) // This works, but what other combinations do?
In Ihrem Fall wollen Sie
def closing[T <: { def close() }] ...
PS Wenn Sie das wirklich viel verwenden möchten, sollten Sie wahrscheinlich auch spielen
class D extends B { override def f = 6 }
class E extends A { override def f() = 6 }
und sehen was use
Sie müssen jeweils verwenden.