Почему эта граница структурного типа не работает, как и ожидалось?
-
24-10-2019 - |
Вопрос
Я пытаюсь написать простой вспомогательный метод, который получает что -то, что может быть закрыто, и некоторая функция, которая получает первое и гарантирует, что «ближайший» закрыт после выполнения функции.
Например, я хочу использовать его так:
closing(new FileOutputStream("/asda"))(_.write("asas"))
Мой импл
object Helpers {
def closing[T <: { def close }](closeable: T)(action: T => Unit): Unit =
try action apply closeable finally closeable close
}
Но при попытке составить этот простой тест:
object Test {
import Helpers._
closing(new FileOutputStream("/asda"))(_.write("asas"))
}
Компилятор жалуется:
Предполагаемый тип аргументов [java.io.fileOutputStream] Не соответствует границам параметров типа Method Claying [t <: AnyRef {def Close: Unit}
Есть идеи почему?
Решение
Вам нужно написать
def closing[T <: { def close() }]
Существует разница в Scala между методами с пустыми скобками и методами без скобок вообще.
Другие советы
Границы типа сложны. В частности, Scala отслеживает количество списков параметров в дополнение к самим параметрам. Попробуйте это!
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?
В вашем случае вы хотите
def closing[T <: { def close() }] ...
PS, если вы действительно планируете использовать это много, вы, вероятно, также должны играть с
class D extends B { override def f = 6 }
class E extends A { override def f() = 6 }
и посмотреть, что use
Вам нужно использовать в каждом случае.