Scala中Option.fold在函数内外行为差异及正确用法咨询
1. 行为差异的原因
这个问题完全是Scala的泛型类型推断规则导致的,和是否写在函数内部没有本质关系:
- Scala中
None的原生类型是Option[Nothing],Nothing是Scala所有类型的子类型,所以Option[Nothing]可以兼容任意Option[T]类型,但前提是编译器能推断出T是什么。 - 你定义
makeUpper函数时,入参明确标注了Option[String]类型,当你传入None时,编译器会自动将None向上转型为Option[String],此时调用fold时,第二个函数的入参类型被确定为String,调用toUpperCase完全合法。不存在所谓的"None转换为Option.empty[String]",只是正常的子类型向上转型。 - 你直接在函数外写
None.fold("b"){ _.toUpperCase }时,没有任何上下文提示编译器这个None应该对应什么类型的Option,编译器只会按Option[Nothing]处理,Nothing类型没有toUpperCase方法,自然报错。 - 而
Option.empty[String]已经显式指定了泛型参数为String,类型明确,所以运行正常。
2. 正确的处理方式
完全不需要把Option处理逻辑套在其他函数内部,只要给编译器足够的类型提示即可,常见的处理方式有以下几种:
- 给单独的
None显式标注类型
(None: Option[String]).fold("b"){ _.toUpperCase }
- 给
fold方法指定泛型参数
None.fold[String]("b"){ _.toUpperCase }
- 处理已经明确泛型的Option返回值时不需要额外操作
如果是调用其他返回Option[T]的函数,只要函数签名已经明确了T的类型,直接处理即可:
// 函数签名已经明确返回Option[String] def queryUserName(userId: Long): Option[String] = { if (userId == 1) Some("张三") else None } // 直接调用fold完全没问题,不需要额外套函数 queryUserName(2).fold("匿名"){ _.toUpperCase }
内容的提问来源于stack exchange,提问作者Jonathan Spiller
相关产品推荐
相关产品推荐

