Polymorphic Methods in Scala- why is this allowed?
我在scala中具有以下多态方法:
1 2 3 4 |
尽管我已指定item1和item2应该具有相同的类型" S",但以下内容仍可以正常编译。我需要使用隐式证据来做些什么吗?
需要明确的是,我实际上希望编译器抱怨它们不是同一类型,但这似乎让我继续前进,这使我感到困惑。谢谢。
1 | println(addTwoThings("1",2)) |
在没有显式使用
要找出为什么
的准确推断
1 2 3 4 5 | scala> def addTwoThings[S](item1:S, item2:S): S = item1 addTwoThings: [S](item1: S, item2: S)S scala> addTwoThings(1,"1") res5: Any = 1 |
您可能会注意到类型
因此,这里有几种解决方案:
1)如果您可以在方法的签名中允许两个类型参数,请使用以下解决方案:
1 2 3 |
注意:ev2对于检查可能是多余的,但是它提供了更完整的相等性,请参见Scala:使用隐式证据的通用方法无法编译
实验:
1 2 3 4 5 6 7 | scala> addTwoThings(1,"1") <console>:18: error: Cannot prove that Int =:= String. addTwoThings(1,"1") ^ scala> addTwoThings("2","1") res11: String = 2 | 1 |
2)或者您可以使用在Scala中类型不相等的证据来排除
1 2 3 4 5 6 |
实验:
1 2 3 4 5 6 7 8 9 10 |
注意:这种方法不需要精确的类型相等,因此如果
注2:编译器提供的错误很难理解,更多信息在这里-使用无形类型不等式时如何自定义Scala模糊不清的隐式错误
3)另一种方法正在出现:
1 |
实验:
1 2 3 4 5 6 7 8 9 | scala> addTwoThings(1)(1) res8: String ="" scala> addTwoThings(1)("1") <console>:18: error: type mismatch; found : String("1") required: Int addTwoThings(1)("1") ^ |
类型推断不会寻找咖喱参数的普通超类型(您可以在此处阅读更多内容)
再一次,这就是Scala编译器的类型推断问题。
您必须给出明确的类型来指导编译器
1 | addTwoThings[String]("1",2) |
以上将给出编译错误。
您的代码起作用的原因
String和Int的常见超级类型是Any。因此,Scala编译器假定函数中的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | scala> def addTwoThings[S](item1:S, item2:S) = | { | item1 +" |" + item2 | } addTwoThings: [S](item1: S, item2: S)String scala> println(addTwoThings("1",2)) 1 | 2 scala> println(addTwoThings[String]("1",2)) <console>:22: error: type mismatch; found : Int(2) required: String println(addTwoThings[String]("1",2)) |