编译close方法的时间结构类型

时间:2017-02-24 09:49:16

标签: scala reflection macros shapeless structural-typing

我的项目中有以下辅助方法:

def close(c: Closeable) {
  Option(c).foreach(s => Try(s.close))
}

我有一些类有一个close方法但没有实现Closeable。如果我更改辅助方法以使用结构类型,我仍然可以在这些类上使用它:

def close(c: {def close()}) {
  Option(c).foreach(s => Try(s.close))
}

然而,这引入了反射的使用,这是我想在运行时避免的。

有没有办法在不引起运行时反射的情况下使用类似于结构类型的东西?

即使Shapeless允许对字段进行泛型访问,也许隐式参数+宏可以用同样的方式访问方法?

1 个答案:

答案 0 :(得分:2)

使用traits实现类型类模式。 当我编写原始解决方案时,边缘有点粗糙,因为我假设快速搜索转换结构边界到上下文边界会得到比我写的更好的解释。情况似乎并非如此。以下是编译解决方案。

object Closeables {
  trait MyCloseable[A] {
    def myClose(a: A): Unit
}

  object MyCloseable {
    implicit object MyCanBeClosed extends MyCloseable[CanBeClosed] {
      def myClose(c: CanBeClosed) = c.nonStandardClose()
    }
  }
}

class CanBeClosed {
  def nonStandardClose(): Unit = println("Closing")
}

import Closeables._
object Test extends App {
  def functionThatCloses[A: MyCloseable](a: A) {
    implicitly[MyCloseable[A]].myClose(a)
  }
  def functionThatClosesExplicit[A](a: A)(implicit ev: MyCloseable[A]) {
    ev.myClose(a)
  }
  val c = new CanBeClosed
  functionThatCloses(c)
  functionThatClosesExplicit(c)
  functionThatCloses(c)(MyCloseable.MyCanBeClosed)
  functionThatClosesExplicit(c)(MyCloseable.MyCanBeClosed)
}

对于functionThatCloses可以接受的每种类型的类,您必须在MyCloseables中定义和隐式对象。

编译器查看functionThatCloses中绑定的上下文,并将其转换为具有functionThatClosesExplicitly定义的函数。

编译器比从MyCloseables对象中“查找”定义中的隐式“证据”并使用它。