4

我正在尝试使用新的 Scala 2.10implicit class机制将 a 转换java.sql.ResultSetscala.collection.immutable.Stream. 在 Scala 2.9 中,我使用以下代码,该代码有效:

/**
 * Implicitly convert a ResultSet to a Stream[ResultSet]. The Stream can then be
 * traversed using the usual methods map, filter, etc.
 *
 * @param resultSet the Result to convert
 * @return a Stream wrapped around the ResultSet
 */
implicit def resultSet2Stream(resultSet: ResultSet): Stream[ResultSet] = {
  if (resultSet.next) Stream.cons(resultSet, resultSet2Stream(resultSet))
  else {
    resultSet.close()
    Stream.empty
  }
}

然后我可以像这样使用它:

val resultSet = statement.executeQuery("SELECT * FROM foo")
resultSet.map {
  row => /* ... */
}

implicit class我想出的看起来像这样:

/**
 * Implicitly convert a ResultSet to a Stream[ResultSet]. The Stream can then be
 * traversed using the usual map, filter, etc.
 */
implicit class ResultSetStream(val row: ResultSet)
  extends AnyVal {
  def toStream: Stream[ResultSet] = {
    if (row.next) Stream.cons(row, row.toStream)
    else {
      row.close()
      Stream.empty
    }
  }
}

但是,现在我必须调用toStreamResultSet这会破坏“隐式”部分:

val resultSet = statement.executeQuery("SELECT * FROM foo")
resultSet.toStream.map {
  row => /* ... */
}

我究竟做错了什么?

我还应该使用implicit defandimport scala.language.implicitConversions来避免“功能”警告吗?

更新

ResultSet这是将 转换为scala.collection.Iterator(仅 Scala 2.10+)的替代解决方案:

/*
 * Treat a java.sql.ResultSet as an Iterator, allowing operations like filter,
 * map, etc.
 *
 * Sample usage:
 * val resultSet = statement.executeQuery("...")
 * resultSet.map {
 *   resultSet =>
 *   // ...
 * }
 */
implicit class ResultSetIterator(resultSet: ResultSet)
extends Iterator[ResultSet] {
  def hasNext: Boolean = resultSet.next()
  def next() = resultSet
}
4

1 回答 1

4

I don't see a reason here to use implicit classes. Stick to you first version. Implicit classes are mainly useful (as in "concise") to add methods to existing types (the so called "enrich my library" pattern). It is just syntactic sugar for a wrapper class and an implicit conversion to this class.

But here you are just converting (implicitly) from one preexisting type to another preexisting type. There is no need to define a new class at all (let alone an implicit class).

In your case, you could make it work using implicit classes by making ResultSetStream extend Stream and implementing as a proxy to toStream. But that would really a lot fo trouble for nothing.

于 2013-02-06T14:56:43.360 回答