在這個例子中,我希望泛型T是 acase class和 a DAOEntitywith id,所以在抽象實作中,我可以使用該copy方法。
如何定義它?
trait DAOEntity {
def id: String
}
// How to define this generic to force the use of a `case class` to have access to `copy`?
abstract class DAO[T <: DAOEntity] {
def storeInUppercase(entity: T): T = entity.copy(id = entity.id)
}
case class MyEntity(id: String) extends DAOEntity
class MyEntityDAO extends DAO[MyEntity] {
// Other stuff
}
uj5u.com熱心網友回復:
沒有辦法知道一個型別是否是 a case class。
即使有,你也不會得到copy方法。該語言沒有提供對建構式進行抽象的方法;因此,擴展名copy和工廠(apply在同伴上)都沒有。這是有道理的,這種函式的型別簽名是什么?
你可以做的是創建一個類似工廠的型別類并要求它:
trait DAOFactory[T <: DAOEntity] {
def copy(oldEntity: T, newId: String): T
}
object DAOFactory {
def instance[T <: DAOEntity](f: (T, String) => T): DAOFactory[T] =
new DAOFactory[T] {
override final def copy(oldEntity: T, newId: String): T =
f(oldEntity, newId)
}
}
可以這樣使用:
abstract class DAO[T <: DAOEntity](implicit factory: DAOFactory[T]) {
def storeInUppercase(entity: T): T =
factory.copy(
oldEntity = entity,
newId = entity.id.toUpperCase
)
}
物體會提供這樣的實體:
final case class MyEntity(id: String, age: Int) extends DAOEntity
object MyEntity {
implicit final val MyEntityFactory: DAOFactory[MyEntity] =
DAOFactory.instance {
case (oldEntity, newId) =>
oldEntity.copy(id = newId)
}
}
// This compile thanks to the instance in the companion object.
object MyEntityDAO extends DAO[MyEntity]
您可以看到這里運行的代碼。
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/422314.html
標籤:
