这是一个让事情变得更有效的机会(对于程序员来说):我发现在Some
中包装内容时会有点烦人,例如Some(5)
。这样的事情怎么样:
implicit def T2OptionT( x : T) : Option[T] = if ( x == null ) None else Some(x)
答案 0 :(得分:31)
你会失去某种类型的安全性并可能引起混淆。 例如:
val iThinkThisIsAList = 2
for (i <- iThinkThisIsAList) yield { i + 1 }
我(无论出于何种原因)认为我有一个列表,当我迭代它时它没有被编译器捕获,因为它被自动转换为Option [Int]。
我应该补充一点,我认为明确导入这是一个很好的隐含,可能不是全局默认。
答案 1 :(得分:26)
请注意,您可以使用explicit implicit模式,以避免混淆并同时保持代码简洁。
我明确暗示的意思是,而不是从T
到Option[T]
的直接转换,您可以转换为包装器对象,该对象提供了从{{1}进行转换的方法到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
我相信这种方式是完全透明的,有助于理解书面代码 - 以一种很好的方式消除对null的所有检查。
注意val x: String = "foo"
x.toOption // Some("foo")
val y: String = null
x.toOption // None
- 您应该只对允许T <: AnyRef
值的类型执行此隐式转换,根据定义,这些值是引用类型。
答案 2 :(得分:12)
隐式转换的一般准则如下:
AnyRef
的 new 类型它只定义了你需要的成员。A
应该子类B
,但由于某种原因没有。在这种情况下,您可以定义从A
到B
的隐式转换。这些是仅情况,适合定义隐式转换。任何其他转换都会匆忙进入类型安全和正确性问题。
T
扩展Option[T]
实际上没有任何意义,显然转换的目的不仅仅是添加成员。因此,这种转换是不可取的。
答案 3 :(得分:1)
看起来这可能会让其他开发人员感到困惑,因为他们会阅读您的代码。
一般来说,似乎implicit
可以帮助从一个对象转换到另一个对象,以减少混乱代码的混乱的代码,但是,如果我有一些变量,它会以某种方式变成{{1}那那似乎很麻烦。
您可能想要显示一些显示正在使用的代码,以查看它会有多混乱。
答案 4 :(得分:0)
您也可以尝试重载该方法:
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
}
答案 5 :(得分:-2)
这对我来说很好,除了它可能不适用于原始T(不能为空)。我猜一个非专业的泛型总是得到盒装基元,所以可能它很好。