首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >隐式转换怪异

隐式转换怪异
EN

Stack Overflow用户
提问于 2017-05-15 22:05:14
回答 1查看 358关注 0票数 11

我试图理解为什么隐式转换在一种情况下有效,而在另一种情况下不起作用。下面是一个示例:

代码语言:javascript
复制
   case class Wrapper[T](wrapped: T)
   trait Wrapping { implicit def wrapIt[T](x: Option[T]) = x.map(Wrapper(_))

   class NotWorking extends Wrapping { def foo: Option[Wrapper[String]] = Some("foo") }

   class Working extends Wrapping { 
      def foo: Option[Wrapper[String]] = {
        val why = Some("foo")
        why
      }
    }

基本上,我有一个从Option[T]Option[Wrapper[T]]的隐式转换,并且正在尝试定义一个函数,该函数返回一个隐式包装的可选字符串。

问题是,为什么当我尝试直接返回Option[String] (上面的NotWorking)时,我得到一个错误(found : String("foo") required: Wrapper[String]),如果我在返回结果之前将结果赋给val,这个错误就会消失。

怎么回事?

EN

回答 1

Stack Overflow用户

发布于 2017-05-15 22:38:49

我不知道这是不是故意的,或者会被认为是一个bug,但我认为这是正在发生的事情。

def foo: Option[Wrapper[String]] = Some("foo")中,编译器会将提供给Some( )的参数的预期类型设置为Wrapper[String]。然后,它看到您提供了一个不是预期的String,因此它查找隐式转换String => Wrapper[String],但找不到,因此失败。

为什么它需要预期的类型,而不只是输入Some("foo")作为Some[String],然后尝试找到一个转换?因为scalac希望能够对以下代码进行类型检查:

代码语言:javascript
复制
case class Invariant[T](t: T)
val a: Invariant[Any] = Invariant("s")

为了让这段代码正常工作,编译器不能只键入Invariant("s")作为Invariant[String],因为这样编译就会失败,因为Invariant[String]不是Invariant[Any]的子类型。编译器需要将预期的"s"类型设置为Any,这样它就可以在为时过晚之前看到"s"Any的一个实例。

为了让这段代码和你的代码都能正确工作,我认为编译器需要某种回溯逻辑,而这似乎是没有的,也许是有很好的理由的。

您的Working代码之所以能够正常工作,是因为这种类型推断不会跨越多行。类似地,val a: Invariant[Any] = {val why = Invariant("s"); why}不能编译。

票数 10
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43981576

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档