【发布时间】:2019-12-07 01:23:04
【问题描述】:
我有一个类似下面例子的场景
// Reads from somewhere and returns List of type A
trait Reader[A] {
def read(): List[A]
}
// Transforms element of type A, performs some operation
// and converts result to string
trait Translator[A] {
def translate(a: A): String
}
object Factory {
def getReader(readerName:String) = {
readerName match {
case "one" => new Reader[String] {
override def read() = List("sasha")
}
case "two" => new Reader[Int] {
override def read() = List(3)
}
case _ => throw new IllegalArgumentException
}
}
def getTranslator(translatorName:String) = {
translatorName match {
case "one" => new Translator[String] {
override def translate (a: String) = a + " " + "nice!!!"
}
case "two" => new Translator[Int] {
override def translate(a: Int) = (a+2).toString
}
case "three" => new Translator[Int] {
override def translate(a: Int) = (a+3).toString
}
case _ => throw new IllegalArgumentException
}
}
}
现在当我执行Factory.getReader("one").read().map(a => Factory.getTranslator("one").translate(a)) 时,我收到一个编译时错误“类型不匹配,预期:_$1,实际:任意”。
如果我没记错的话,编译器说它无法判断阅读器的类型 A 是否与翻译器的类型 A 相同。
我无法在网上找到,我该如何解决这个问题?我在以我的方式定义类时做错了什么吗?
编辑
我有单独的阅读器和翻译器的原因是,他们似乎有不同的工作,我可以将多个翻译器应用于一个阅读器的输出(上面的翻译器 2 和 3 可以应用于阅读器 2 的输出)。
【问题讨论】:
-
两者,
getReader和getTranslator分别返回 Reader[Any] 和 Translator[Any]。因此,您将遇到很多类型推断问题。 - 我假设您只需要每种类型的每个实例。如果是这样,您可以为此使用 typeclasses,如果您有兴趣,我可以发布带有解决方案草图的答案。 -
@LuisMiguelMejíaSuárez 是的,我很想知道。我已经更新了我的问题。
-
嗯,因为您希望每种类型有多个实例,所以 typeclasses 不再适用。让我看看我能不能做点别的。每种类型只有一个实例的限制是否适用于 Reader?
-
"Reader 是否只有一个实例类型的限制?" 没有。
-
想了想。您想要做的事情是不可能的,因为所有类型信息仅在运行时可用......因此编译器无法证明您的程序是正确的。也许你可以玩一下 ClassTags / TypeTags - 但是,我会问,工厂接收字符串的目的是什么?该名称在编译时是否始终可用,这意味着它将保持不变?或者你会从运行时得到它吗?如果最后一个是真的,你真的不能做太多,而是到处添加很多不安全的强制转换,如果任何不匹配,让程序在运行时崩溃
标签: scala generics types type-inference