开发者

Why this structural type bound does not work as expected?

开发者 https://www.devze.com 2023-02-07 00:34 出处:网络
I\'m trying to write a simple helper method that receives something that can be closed and some function which receives the former and ensures the \"closeable\" is closed after executing the function.

I'm trying to write a simple helper method that receives something that can be closed and some function which receives the former and ensures the "closeable" is closed after executing the function.

For example, I want to use it like this:

  closing(new FileOutputStream("/asda"))(_.write("asas"))

My impl is

object Helpers {

  def closing[T <: { def close }](closeable: T)(action: T => Unit): Unit =
    try action 开发者_Go百科apply closeable finally closeable close

}

But when trying to compile this simple test:

object Test {

  import Helpers._

  closing(new FileOutputStream("/asda"))(_.write("asas"))

}

The compiler complains with:

inferred type arguments [java.io.FileOutputStream] do not conform to method closing's type parameter bounds [T <: AnyRef{def close: Unit}]

Any ideas why?


You need to write

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

there is a difference in Scala between methods with empty parentheses and methods without parentheses at all.


Type bounds are tricky. In particular, Scala keeps track of the number of parameter lists in addition to the parameters themselves. Try these out!

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 your case, you want

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

P.S. If you really plan on using this a lot, you probably ought also play with

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

and see which use you need to use in each case.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号