当使用这个lambda速记时,为什么编译器不能选择正确的String.containes方法?

人气:56 发布:2023-01-03 标签: type-inference implicit implicit-conversion scala overloading

问题描述

假设我要检查字符串是否包含中的任何字母

def hasCory(input: String): Boolean = {
  val myName = "cory"
  input.exists(myName.contains)
}

编译器出现以下错误:

error: type mismatch;
found   : CharSequence => Boolean
required: Char => Boolean

Scala提供了我想要的Char-接受方法in StringOps:

但似乎编译器无法看到此方法,除非我将代码更改为以下之一:

input.exists(myName.contains(_))
input.exists(c => myName.contains(c))

相反,在原始示例中,它似乎使用Java String's contains method,这实际上接受CharSequence

这是否按预期工作?为什么编译器看不到我需要Char版本的contains

推荐答案

StringOps为an implicit conversion

@inline implicit def augmentString(x: String): StringOps = new StringOps(x)

和隐式转换仅适用于in three cases:

如果表达式的类型为,并且不符合该表达式的预期类型pt。 在选择.中 对于类型为的,如果选择器不表示的可访问成员。 在选择.(Args)中 对于类型为的,如果选择器表示的某些成员,但这些成员都不适用于参数args。

当您编写myName.contains时,它不是这三种情况中的一种(特别是 不是第二种情况,因为containsString)的可访问成员,因此StringOps无法应用,并且它是String#contains(CharSequence)和类型不匹配错误。

当您编写myName.contains(_)c => myName.contains(c)时,它是第三个大小写,因此StringOps可以应用,并且它在隐式转换之后是StringOps#contains(Char)

所以是的,它工作正常。

18