我正在尝试使用新的Scala 2.10 implicit class
机制将java.sql.ResultSet
转换为scala.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
}
}
}
但是,现在我必须在toStream
上调用ResultSet
,这会打败“隐含”部分:
val resultSet = statement.executeQuery("SELECT * FROM foo")
resultSet.toStream.map {
row => /* ... */
}
我做错了什么?
我是否仍应使用implicit def
和import 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
}
答案 0 :(得分:4)
我没有看到使用隐式类的原因。坚持你的第一个版本。隐式类主要用于(如“简明”)将方法添加到现有类型(所谓的“丰富我的库”模式)。 它只是包装类的语法糖和对此类的隐式转换。
但在这里,您只是(隐式地)从一个预先存在的类型转换为另一个预先存在的类型。根本不需要定义新类(更不用说隐式类)了。
在您的情况下,可以通过使ResultSetStream
扩展Stream
并将其作为toStream
的代理实现,使其使用隐式类。但这对于什么都没有麻烦。