【发布时间】:2009-11-17 03:16:22
【问题描述】:
这是一个让事情变得更有效率的机会吗(对于程序员来说):我发现将东西包装在Some 中有点烦人,例如Some(5)。像这样的东西呢:
implicit def T2OptionT( x : T) : Option[T] = if ( x == null ) None else Some(x)
【问题讨论】:
标签: scala scala-option
这是一个让事情变得更有效率的机会吗(对于程序员来说):我发现将东西包装在Some 中有点烦人,例如Some(5)。像这样的东西呢:
implicit def T2OptionT( x : T) : Option[T] = if ( x == null ) None else Some(x)
【问题讨论】:
标签: scala scala-option
您会失去一些类型安全性并可能导致混淆。 例如:
val iThinkThisIsAList = 2
for (i <- iThinkThisIsAList) yield { i + 1 }
我(无论出于何种原因)认为我有一个列表,当我迭代它时它没有被编译器捕获,因为它被自动转换为 Option[Int]。
我应该补充一点,我认为这是显式导入的一个很好的隐式,可能不是全局默认值。
【讨论】:
请注意,您可以使用explicit implicit 模式,这样可以避免混淆并同时保持代码简洁。
我的意思是显式隐式不是从T 到Option[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)
...我可能会为它找到一个比 Optionable 更好的名称,但现在您可以编写如下代码:
val x: String = "foo"
x.toOption // Some("foo")
val y: String = null
x.toOption // None
我相信这种方式是完全透明的,有助于理解所编写的代码 - 以一种很好的方式消除了对 null 的所有检查。
注意T <: AnyRef - 您应该只对允许null 值的类型进行这种隐式转换,根据定义,这些类型是引用类型。
【讨论】:
隐式转换的一般准则如下:
AnyRef 且仅定义您需要的成员。A 类型应该 继承B,但由于某种原因没有。在这种情况下,您可以定义从 A 到 B 的隐式转换。这些是仅 适合定义隐式转换的情况。任何其他转换都会很快遇到类型安全和正确性问题。
T扩展Option[T]确实没有任何意义,显然转换的目的不仅仅是增加成员。因此,这种转换是不可取的。
【讨论】:
在其他开发人员阅读您的代码时,这似乎会让他们感到困惑。
一般来说,implicit 似乎有助于从一个对象转换到另一个对象,以消除可能使代码混乱的令人困惑的转换代码,但是,如果我有一些变量并且它以某种方式变成了 Some,那么那将好像很麻烦。
你可能想放一些代码来显示它正在被使用,看看它会有多混乱。
【讨论】:
你也可以尝试重载方法:
def having(key:String) = having(key, None)
def having(key:String, default:String) = having(key, Some(default))
def having(key: String, default: Option[String]=Option.empty) : Create = {
keys += ( (key, default) )
this
}
【讨论】:
这对我来说看起来不错,但它可能不适用于原始 T(不能为空)。我猜一个非专业的泛型总是得到盒装的原语,所以可能没问题。
【讨论】: