scala - 如何在需要具体类型的情况下使用具有存在类型的变量?
问题描述
这个人为的例子说明了我的问题的本质:
trait Producer[X] {def make(): X }
sealed trait MyProducer[X] extends Producer[X]
case class MyProducerA(n: Int) extends MyProducer[Int] {...}
case class MyProducerB(s: String) extends MyProducer[String] {...}
def doWithProducer[P <: Producer[_]](producer: P): P = {
makePair(producer) // the compiler fails to infer the type parameter
producer
}
def makePair[X](p: Producer[X]): (X, X) = (p.make(), p.make())
// this is how I need to call the method
val myProducer: MyProducer[_] = ???
doWithProducer(myProducer)
该doWithProducer()
方法不能具有产品类型的类型参数,因为子类型MyProducer
具有不同的产品类型(或者我在这里已经错了吗?)。在里面doWithProduct()
我知道我有一个具有类型参数的 Producer 的具体实例。我不在乎哪个,但它有一个。但是,编译器无法弄清楚这一点。
我可以在不更改方法签名的情况下解决这个问题吗?
更新:我觉得好奇并且让我假设必须有一种方法是我实际上可以在类型变量中间接捕获产品的类型:
def duplicate[X](p: X): (X, X) = (p, p)
duplicate(producer.make)
但是,我仍然无法获得Producer[X]
.
解决方案
P <: Producer[_]
表示它P
是某种未知类型的生产者。如果您想说它P
是某个要推断的已知类型的生产者,则不应使用存在类型。
尝试
def doWithProducer[X, P <: Producer[X]](producer: P): P = {
makePair(producer)
producer
}
或者
def makePair(p: Producer[_]): (Any, Any) = (p.make(), p.make())
您必须更改至少一种方法的签名doWithProducer
才能makePair
使它们编译。
或者你可以投
def doWithProducer[P <: Producer[_]](producer: P): P = {
makePair(producer.asInstanceOf[Producer[Any]])
producer
}
推荐阅读
- python - 出现新条目时获取计数
- laravel - 更新数据库或文件中的汇率
- php - PHP 7.1.29 - 字符串中的数字行为错误
- c - 将 cjson json 转换为字符串
- angular - Mat-Autocomplete formControlName
- javascript - 后期输出的差异
- dom - Puppeteer 的 `page.content()` 总是使用 UTF-8 还是页面特定的字符集?
- javascript - 如何对组件进行引用并监听外部点击?
- ios - JavaScript 桥接 - 替代 window.webkit.messageHandlers.handlerNameHere.postMessage()
- amazon-web-services - 使用 aws 命令行显示红移查询