可以/应该在Scala中添加/创建从T到Option [T]的隐式转换吗?

Ale*_*ack 35 scala scala-option

这是一个让事情变得更有效率的机会(对于程序员而言):我觉得不得不把事情包裹起来Some,例如Some(5).这样的事情怎么样:

implicit def T2OptionT( x : T) : Option[T] = if ( x == null ) None else Some(x)
Run Code Online (Sandbox Code Playgroud)

Mit*_*ins 31

你会失去某种类型的安全性并可能引起混淆.例如:

  val iThinkThisIsAList = 2 
  for (i <- iThinkThisIsAList) yield { i + 1 }
Run Code Online (Sandbox Code Playgroud)

我(无论出于何种原因)认为我有一个列表,当我迭代它时它没有被编译器捕获,因为它被自动转换为Option [Int].

我应该补充一点,我认为明确导入这是一个很好的隐含,可能不是全局默认.


Fla*_*gan 27

请注意,您可以使用显式隐式模式,以避免混淆并同时保持代码简洁.

我所说的显式隐式是指而不是直接转换TOption[T]你可以转换为包装器对象,它提供了从中进行转换的T方法Option[T].

class Optionable[T <: AnyRef](value: T) {
  def toOption: Option[T] = if ( value == null ) None else Some(value)
}

implicit def anyRefToOptionable[T <: AnyRef](value: T) = new Optionable(value)
Run Code Online (Sandbox Code Playgroud)

...我可能会找到比它更好的名字Optionable,但现在你可以编写如下代码:

val x: String = "foo"
x.toOption // Some("foo")

val y: String = null
x.toOption // None
Run Code Online (Sandbox Code Playgroud)

我相信这种方式是完全透明的,有助于理解编写的代码 - 以一种很好的方式消除对null的所有检查.

请注意T <: AnyRef- 您应该仅对允许null值的类型执行此隐式转换,根据定义,这些值是引用类型.

  • `Option(x)`(而不是`Some(x)`)也适用于null. (8认同)
  • @ flaviu-cipcigan,做同样但更短 - 隐式类IntWithTimes [T](x:T){def toOption:Option [T] = if(x!= null)Option(x)else None} (2认同)

Dan*_*wak 12

隐式转换的一般准则如下:

  • 当你需要向一个类型添加成员(一个"开放类";也就是"pimp my library"模式)时,转换为一个扩展的类型AnyRef,它只定义你需要的成员.
  • 当您需要"更正"继承层次结构时.因此,你有一些类型的A哪些应该子类B,但并没有因为某些原因.在这种情况下,你可以定义从隐式转换AB.

这些是唯一适合定义隐式转换的情况.任何其他转换都会匆忙进入类型安全和正确性问题.

T扩展真的没有任何意义Option[T],显然转换的目的不仅仅是增加成员.因此,这种转换是不可取的.