Scala Option隐式转换-错误的做法或缺少功能? [英] Scala Option implicit conversion - Bad practice or missing feature?

查看:116
本文介绍了Scala Option隐式转换-错误的做法或缺少功能?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我将我的数据模型表示为案例类,键入可能为null的Option值.

I represented my data model as case classes typing values that may be null as Option.

case class Document(id: Long, title: String, subtitle: Option[String])

现在,我尝试实例化案例类:

Now I try to instantiate the case class:

Document(123, "The Title", "Subtitle") // Doesn't work

但是不行!这不起作用,我必须将可选值包装在Some中.

But NOPE! This doesn't work, I have to wrap the optional value in a Some.

Document(123, "The Title", Some("Subtitle")) // Works

Scala通常对类型非常聪明,但是为什么硬编码文字或(与此有关的任何字符串)不同于null/None的原因不言而喻呢?

Scala is very clever about types in general, but why is it not self-evident that a hard coded literal, or (any string for that matter) is a different than null/None?

我能够解决此问题,并通过添加此隐式转换使Scala变得更聪明"

I was able to fix this and make Scala "more clever" by adding this implicit conversion

implicit def autoSome[T](any:T) = Some(any)
Document(123, "The Title", "Subtitle") // Now it works!

问题:我是该语言中唯一应该提供隐式转换的人T-> Some(T)开箱即用吗?还是有我不知道默认情况下到处都有如此广泛的隐式性的陷阱?

Question: Am I the only one that the language should provide implicit conversion T -> Some(T) out of the box? Or is there any gotchas that I'm not aware of about having so broad implicit everywhere by default?

推荐答案

这可能会引起许多问题.这里的问题不是您可能会想到的,而是您认为不会发生的事情.也就是说,如果您创建另一个对Option类型可用的隐式类,则可能最终创建您从未打算发生的虚假结果,即,非重载类型中存在重载类型的运算符.

This can cause untold number of problems. The issue here isn't what you might think but what you don't think could happen. That is, if you make another implicit class that works on Option types you could wind up creating artificial results that you never intended to happen, i.e. operators for your overloaded types being present in your non-overloaded types.

 implicit class OptDouble(opt: Option[Double]) extends Any{
   def *(x: Double) = Some((opt getOrElse 0.0) * x)
   def ^(x: Double) = Some(Math.power(opt getOrElse 1.0, x))
 }

 val z = q^4.5

z的类型是Option[Double].您不会期望发生这种情况,但是首先Scala将隐式转换为Option,然后使用隐式类调用^运算符.现在,人们在看您的代码时会不知所措,想知道为什么要有Option.当人们为远离Option而奋斗时,您可能会开始在代码周围散布一些防御性的x getOrElse 0.0(是的,这是基于个人经验.)

The type of z is Option[Double]. You wouldn't expect that to happen but first Scala did an implicit conversion to Option and then it used the implicit class to call the ^ operator. Now people looking at your code are going to be scratching their heads wondering why they have an Option. You might start seeing a few defensive x getOrElse 0.0 sprinkled around the code as people fight to keep Option away (and yes, this is from personal experience.)

也就是说,您应该在对象上使用另一个apply:

That said, what you should do is use another apply on the object:

object Document{
  def apply(id: Long, title: String, subtitle: String) = new Document(id, title, Some(subtitle))
}

只要您没有为subtitle定义默认值(即subtitle: Option[String] = None),它将执行您希望执行的所有操作.

which will do everything you wanted it to do as long as you don't have a default defined for subtitle, i.e. subtitle: Option[String] = None.

这篇关于Scala Option隐式转换-错误的做法或缺少功能?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆