让我直接谈谈我在处理类型边界时遇到的问题
让我们考虑以下内容。。。我创建了一个类似的函数"foo">
def foo[A,B](x:A,y:B):(A,B)=(x,y)
我在scala工作表中调用了foo,比如
foo("Mars",2400)
我得到了类似的结果
res0: (String, Int) = (Mars,2400)
注意火星和2400的推断类型
现在,我想强制函数"foo"接受Integers、float或Doubles(AnyVal的任何类型的子类型(
为了强制执行,我写了一个类似的代码
def fooNew[A<:B,B](x:A,y:B):(A,B)=(x,y)
从前面的代码中推断出的类型是(String,Int(,当我调用类似的fooNew时
fooNew("Saturn",2400)
我很惊讶地发现,编译器确实让我的代码通过了,并且没有引发错误,相反,它确实给出了类似的输出
res0: (String, Any) = (Saturn,2400)
现在,想要的强制执行方式在这里不起作用。我做过类似的事情吗
def fooNew[A<:B,B<:AnyVal](x:A,y:B):(A,B)=(x,y)
编译器肯定会给我带来一个错误,它确实犯了!
Error:(2, 2) inferred type arguments [String,Any] do not conform to method fooNew's type parameter bounds [A <: B,B <: AnyVal]
fooNew("Saturn",2400);}
我想问,为什么编译器不将类型设置为Int,而是推断类型Any,并让我的代码通过类型检查
我是否总是需要强制第二个类型为AnyVal的子类型,而不是让编译器为我推断它?还是编译器中的错误
如果您发现我的问题有误导性或达不到您的期望,请原谅。
目前我正在使用scala库2.11.8
感谢
def fooNew[A<:B,B](x:A,y:B):(A,B)=(x,y)
在上面的例子中,您将类型参数A声明为类型参数B的子类型。当您将A传递为String,将B传递为Int时,编译器会向上遍历类层次结构,为B找到合适的类型,这样Int是B,String也是B
您可以考虑使用具有推断类型的原始声明,如"查找A
和B
,使x
具有类型A
,y
具有类型B
,并且A
是B
的子类型"。由于Any
0和B = Any
满足这些条件,编译器正确地推断出它们(也有其他解决方案,例如A = B = Any
,但这一个是最具体的(。
但是,您可以更改声明,告诉编译器"找到A
和B
,使x
具有类型A
,y
具有类型B
,然后检查A
是B
的子类型"。具体操作如下:
def fooNew[A,B](x:A,y:B)(implicit evidence: A <:< B): (A,B)=(x,y)
这是因为编译器将只使用第一个参数列表来推断A
和B
。搜索"广义类型约束"以查找有关<:<
和=:=
的更多信息。