我怎样才能做到这一点:
final case class ChairId(id: String)
trait GeneratorLike[TO, TC <: AbstractId] {
val prefix: String
def generate(): TC = TO.apply(prefix + "-" + UUID.randomUUID())
}
implicit object ChairIdGenerator extends GeneratorLike[ChairId.type, ChairId] {
val prefix: String = "CHAIR"
}
implicit def IdFn[TO, TC <: AbstractId](x: TO)(implicit ev: GeneratorLike[TO, TC]): GeneratorLike[TO, TC] = ev
//right now I can call:
ChairId.generate()
我不想为那种情况定义伴侣对象,我想知道是否有机会使用implicits来扩展对象?
当我这样做时(我使用TO作为TypeObject和TC作为TypeClass命名)idFn[TO, TC]
我希望TO成为实现def apply(id: String): TC
的对象我可以强制执行吗?我将如何使用此功能?在类型参数上调用函数是完全不可能的:/
答案 0 :(得分:2)
无法在类型参数上调用方法,因为它代表类型而不是对象。您可以在对象上调用方法,因为它是存在的东西,但类型是抽象概念。我不知道你想要隐含地将generate()
添加到伴侣对象的动机是什么,因为它实际上需要定义隐式GeneratorLike
的代码与定义{ChairId
的伴侣一样多。 1}}。
如果你强制GeneratorLike
拥有apply
方法(可以通过案例类apply
实现),并删除第一个类型参数,这将有效。
trait GeneratorLike[TC <: AbstractId] { this: Singleton =>
val prefix: String
def apply(id: String): TC
def generate(): TC = apply(prefix + "-" + UUID.randomUUID())
}
abstract class AbstractId
final case class ChairId(id: String) extends AbstractId
object ChairId extends GeneratorLike[ChairId] {
val prefix = "CHAIR"
}
scala> ChairId.generate()
res0: ChairId = ChairId(CHAIR-60bb01c7-af95-46c7-af45-0b3fa78b3080)
答案 1 :(得分:0)
结构类型在JVM上并不是一个特别好的主意,因此总是尽量避免使用def test(x: {def apply(s: String)}): TC
类型的东西,因为它是使用反射实现的,这可能是一种性能明智的狗。
其次,您应该避免在val
内使用trait
。阅读here。
您考虑的方法实际上是正确的方法,即类型类。
trait HasGenerator[T] {
def apply(uuid: String): T
def generate[T : Generator] = apply(Generator[T].generate)
}
final case class ChairId(id: String)
object ChairId extends HasGenerator[ChairId]
trait Generator[TO] {
def prefix: String
def generate(): String = prefix + "-" + UUID.randomUUID()
def apply(): String = generate
}
object Generator {
def apply[T : Generator] = implicitly[Generator[T]]
}
// Notice .type is not necessary
implicit object ChairIdGenerator extends Generator[ChairId] {
override def prefix = "CHAIR"
}
为什么不使用:
ChairId(Generator[ChairId])
这一切看起来都有些过分,所以你可以很容易地以某种方式。值得更多地满足您的要求是值得的,因为类型类似乎还不是非常必要。你可以这样做:
<强>更新强>
如果你使用我上面添加的HasGenerator
之类的东西与伴侣对象一起使用,你现在可以成功呼叫ChairId.generate()