Pourquoi ce type de structure lié ne fonctionne pas comme prévu?
-
24-10-2019 - |
Question
Je suis en train d'écrire une méthode simple d'aide qui reçoit quelque chose qui peut être fermé et une fonction qui reçoit l'ancien et assure la « refermable » est fermée après l'exécution de la fonction.
Par exemple, je veux l'utiliser comme ceci:
closing(new FileOutputStream("/asda"))(_.write("asas"))
Mon impl est
object Helpers {
def closing[T <: { def close }](closeable: T)(action: T => Unit): Unit =
try action apply closeable finally closeable close
}
Mais quand vous essayez de compiler ce test simple:
object Test {
import Helpers._
closing(new FileOutputStream("/asda"))(_.write("asas"))
}
Le compilateur se plaint avec:
arguments de type inférées [Java.io.FileOutputStream] ne pas être conforme au type de fermeture de la méthode limites des paramètres [T <: AnyRef {def Fermer: Unité}]
Toutes les idées pourquoi?
La solution
Vous devez écrire
def closing[T <: { def close() }]
il y a une différence entre les méthodes de Scala avec des parenthèses vides et des méthodes sans parenthèses du tout.
Autres conseils
limites de type sont difficiles. En particulier, Scala garde la trace du nombre de listes de paramètres en plus des paramètres eux-mêmes. Essayez-les!
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?
Dans votre cas, vous voulez
def closing[T <: { def close() }] ...
P.S. Si vous prévoyez vraiment sur l'utilisation de ce lot, vous devriez probablement jouer avec
class D extends B { override def f = 6 }
class E extends A { override def f() = 6 }
et que vous voyez use
besoin d'utiliser dans chaque cas.