好的,这是基于字符串的版本,它可能存在关于许多极端情况的错误,并且需要实现者以提供隐式 TypeTag 的形式生成样板:
import shapeless._
import scala.collection.mutable
import scala.reflect.runtime.universe._
trait IdGen[L <: HList] {
implicit val ltag: TypeTag[L]
private val idGens = mutable.Map(typeTag[L].toString.split("""::\[""").toList.tail.map(_.split(""",shapeless""")(0) -> 0L): _*)
def id[T: TypeTag] = {
val t = typeOf[T].toString
val id = idGens(t)
idGens(t) = id + 1L
id
}
}
简单的测试类:
import java.util.NoSuchElementException
import org.junit.{Assert, Test}
import shapeless._
import reflect.runtime.universe._
class Person
class Booking
class Charge
class MyDao(implicit val ltag: TypeTag[Person :: Booking :: HNil]) extends IdGen[Person :: Booking :: HNil]
class Testy {
val myDao = new MyDao
@Test(expected = classOf[NoSuchElementException])
def test {
Assert.assertEquals(0L, myDao.id[Person])
Assert.assertEquals(1L, myDao.id[Person])
Assert.assertEquals(0L, myDao.id[Booking])
myDao.id[Charge]
}
}
看到更好的实现会很有趣。