提供的代码片段是一个虚构的简约示例,仅用于演示问题,与实际业务逻辑类型无关。
在下面的代码中,我们在类型内部有一个嵌套Entry
类型Registry
。
class Registry[T](name: String) {
case class Entry(id: Long, value: T)
}
这是有道理的,因为不同注册表的条目是不同的、无与伦比的类型。
然后我们可能有一个隐式的 Ops 类,例如,在测试中使用,它将我们的注册表绑定到一些测试存储实现,一个简单的可变映射
object testOps {
import scala.collection.mutable
type TestStorage[T] = mutable.Map[Long, T]
implicit class RegistryOps[T](val self: Registry[T])(
implicit storage: TestStorage[T]
) {
def getById(id: Long): Option[self.Entry] =
storage.get(id).map(self.Entry(id, _))
def remove(entry: self.Entry): Unit = storage - entry.id
}
}
问题是:内部构造的Entry
Ops 包装器被视为原始 Registry 对象无法比拟的类型
object problem {
case class Item(name: String)
val items = new Registry[Item]("elems")
import testOps._
implicit val storage: TestStorage[Item] =
scala.collection.mutable.Map[Long, Item](
1L -> Item("whatever")
)
/** Compilation error:
found : _1.self.Entry where val _1: testOps.RegistryOps[problem.Item]
required: eta$0$1.self.Entry
*/
items.getById(1).foreach(items.remove)
}
问题是:有没有办法声明 Ops 签名以使编译器了解我们正在使用相同的内部类型?(我也尝试self.type#Entry
过RegistryOps
但没有运气)如果我错过了一些理解并且它们实际上是不同的类型,我将不胜感激任何解释和示例,为什么将它们视为相同可能会破坏类型系统。谢谢!