Почему этот структурный тип не работает, как ожидалось? - PullRequest
4 голосов
/ 25 января 2011

Я пытаюсь написать простой вспомогательный метод, который получает что-то, что может быть закрыто, и некоторую функцию, которая получает первый и гарантирует закрытие "closeable" после выполнения функции.

Например, яхочу использовать это так:

  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] не соответствуют границам параметров типа закрытия метода [T <: AnyRef {def close: Unit}] </p>

Есть идеи почему?

Ответы [ 2 ]

12 голосов
/ 25 января 2011

Вам нужно написать

def closing[T <: { def close() }]

Существует разница в Scala между методами с пустыми скобками и методами без скобок.

7 голосов
/ 25 января 2011

Типовые границы сложно. В частности, 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() }] ...

P.S. Если вы действительно планируете использовать это много, вы, вероятно, должны также играть с

class D extends B { override def f = 6 }
class E extends A { override def f() = 6 }

и посмотрите, какой use вам нужно использовать в каждом конкретном случае.

...