scala 何时使用选项

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9698391/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-22 03:58:26  来源:igfitidea点击:

When to use Option

scala

提问by Soteric

I learn Scala for some time and can't clearly understand the usage of Option. It helps me to avoid null checks when I chain functions (according to docs). That's clear for me :)

学习Scala有一段时间了,并不能清楚地理解Option的用法。它帮助我在链接函数时避免空检查(根据docs)。这对我来说很清楚:)

Next I see that Option can be kind of indicator for developer that null value is possible here and it must be handled. Is it true? If yes should I use Option whereever it's possible? For example

接下来我看到 Option 可以作为开发人员的一种指示器,表明此处可能存在空值并且必须对其进行处理。这是真的吗?如果是,我应该尽可能使用 Option 吗?例如

class Racer {
    val car = new Car()
}

I have Racer class and I'm sure that car field can't be null (because it's constant and get a value when I create Racer instance). No need for Option here.

我有 Racer 类,并且我确定 car 字段不能为空(因为它是常量并且在我创建 Racer 实例时获得一个值)。这里不需要 Option。

class Racer {
    var car = new Car()
}

Here I make it so that the car can change. And it's possible for someone to assign null to car. Should I use Option here? If yes I notice that all my class fields are candidates for Option. And my code looks like this

在这里,我这样做是为了让汽车可以改变。并且有人可以将 null 分配给 car。我应该在这里使用 Option 吗?如果是,我注意到我所有的类字段都是 Option 的候选者。我的代码看起来像这样

class Racer {
    var car: Option[Car] = None
    var currentRace: Option[Race] = None
    var team: Option[Team] = None
    ...
}

Does it look good? For me it seems kind of Option overusing.

它看起来好吗?对我来说,这似乎是一种过度使用的 Option。

def foo(): Result = {
    if( something )
        new Result()
    else
        null
}

I have a method which can return null. Should I return Option instead? Should I always do it if it's possible for method to return null?

我有一个可以返回空值的方法。我应该返回 Option 吗?如果方法可以返回 null,我应该总是这样做吗?

Any thoughts about it would be helpful. Thanks in advance!

任何关于它的想法都会有所帮助。提前致谢!

My question is similiar to Why optionbut I think it's not the same. It's more about when,not why.:)

我的问题类似于为什么选项,但我认为它不一样。更多的是关于什么时候,而不是为什么。:)

回答by Jesper

You should avoid nullas much as possible in Scala. It really only exists for interoperability with Java. So, instead of null, use Optionwhenever it's possible that a function or method can return "no value", or when it's logically valid for a member variable to have "no value".

null在 Scala 中你应该尽可能避免。它实际上只是为了与 Java 的互操作性而存在。因此,当函数或方法可能返回“无值”时,或者当成员变量具有“无值”在逻辑上有效时null,请使用,而不是Option

With regard to your Racerexample: Is a Racerreally valid if it doesn't have a car, currentRaceand team? If not, then you shouldn't make those member variables options. Don't just make them options because it's theoretically possible to assign them to null; do it only if logically you consider it a valid Racerobject if any of those member variables has no value.

关于您的Racer示例:Racer如果没有car,currentRace和,则真的有效team吗?如果没有,那么您不应该使用这些成员变量选项。不要只是让它们成为选项,因为理论上可以将它们分配给null; 只有当Racer这些成员变量中的任何一个都没有值时,才在逻辑上将其视为有效对象时才这样做。

In other words, it's best to pretend as if nulldoesn't exist. The use of nullin Scala code is a code smell.

换句话说,最好假装null不存在。采用null在Scala代码是一个代码味道。

def foo(): Option[Result] = if (something) Some(new Result()) else None

Note that Optionhas many useful methods to work with.

请注意,Option有许多有用的方法可以使用。

val opt = foo()

// You can use pattern matching
opt match {
  case Some(result) => println("The result is: " + result)
  case None         => println("There was no result!")
}

// Or use for example foreach
opt foreach { result => println("The result is: " + result) }

Also, if you want to program in the functional style, you should avoid mutable data as much as possible, which means: avoid the use of var, use valinstead, use immutable collections and make your own classes immutable as much as possible.

另外,如果你想以函数式风格进行编程,你应该尽可能避免可变数据,这意味着:避免使用var,使用val替代,使用不可变集合并尽可能使自己的类不可变。

回答by pad

When it comes to functional programming in Scala, Optionis much preferable than nullsince it is type-safe and plays nice with other constructs in the functional paradigm.

当谈到 Scala 中的函数式编程时,它Optionnull因为它是类型安全的并且与函数范式中的其他构造很好地配合使用要好得多。

Especially, you can easily write idiomatic code using high-order functions on Option. This Scala Option Cheat Sheetis a helpful read on the topic.

特别是,您可以使用Option. 这个Scala Option Cheat Sheet是有关该主题的有用读物。

回答by schmmd

While Optioncan makes your class definition look verbose, the alternative is to not know when you need to test whether a variable is defined. I think that in your example, if your class were immutable (all the fields were vals), you would not need so many Options.

虽然Option可以使您的类定义看起来冗长,但另一种方法是不知道何时需要测试是否定义了变量。我认为在你的例子中,如果你的类是不可变的(所有字段都是vals),你就不需要这么多Options。

For your method foo, if you return null, you need to document it and the client needs to read that documentation. Then the client will write a bunch of code like:

对于您的方法foo,如果您返回 null,您需要记录它并且客户端需要阅读该文档。然后客户端会写一堆代码,比如:

val result = foo(x)
if (result != null) {
  println(result)
}

If instead you define footo return an Option[Result], the type system forces the client to handle the possibility of an undefined result. They also have the full power of the collections classes.

相反,如果您定义foo返回一个Option[Result],则类型系统会强制客户端处理未定义结果的可能性。它们还拥有集合类的全部功能。

result foreach println

An additional advantage of using the collections method with an Optioninstead of testing for nullis that if your method is extended to a multi-element collection (such as a List), you might not need to change your code at all. For example, you might initially assume your Racercan only have a single crew, so you define val crew: Option[Crew]and you might test if the crew is older than 30 with crew.forall(_.age > 30).getOrElse(false). Now if you changed the definition to val crew: List[Crew]your old code would still compile and now you would check if all of your crew members are over 30.

将 collections 方法与 anOption而不是 testing for一起使用的另一个优点null是,如果您的方法扩展到多元素集合(例如 a List),则您可能根本不需要更改代码。例如,您最初可能假设您Racer只能拥有一个船员,因此您可以val crew: Option[Crew]使用crew.forall(_.age > 30).getOrElse(false). 现在,如果您将定义更改为val crew: List[Crew]旧代码仍然可以编译,现在您将检查您的所有船员是否都超过 30。

Sometimes you need to deal with nullbecause libraries you are using may return it. For example, when you get a resource, you might get a nullresult. Fortunately, it is easy to defensively wrap results so they are transformed into an option.

有时您需要处理,null因为您正在使用的库可能会返回它。例如,当您获取资源时,您可能会得到一个null结果。幸运的是,很容易对结果进行防御性包装,以便将它们转换为一个选项。

val resource = Option(this.getClass.getResource("foo"))

If getResourcereturned nullthen resourceequals None, and otherwise it is a Some[URL]. Cool!

如果getResource返回nullresource等于None,否则为Some[URL]。凉爽的!

Unfortunately, Optionis likely to have some overhead because it involves an extra object creation. However, that overhead is minimal compared to a null pointer exception!

不幸的是,Option可能会有一些开销,因为它涉及额外的对象创建。但是,与空指针异常相比,这种开销是最小的!

回答by Nicolas

The idea behind Optionsis to get rid off null, so yes, you should use them instead of returning "nullor a value". That's also why, if you want to model optional fields (0..1 relationship with other objects), using Optionis definitely a good thing.

背后的想法Options是摆脱掉null,所以是的,你应该使用它们而不是返回“null或值”。这也是为什么,如果你想对可选字段建模(与其他对象的 0..1 关系),使用Option肯定是一件好事。

The little drawback is that it renders declaration of class with a lot of optional field a bit verbose, as you mentionned.

正如您所提到的,它的小缺点是它使带有许多可选字段的类声明有点冗长。

One more thing, in scala, you are encouraged to use "immutable objects", so in your example, the fields should be some vals. ;)

还有一件事,在 Scala 中,鼓励您使用“不可变对象”,因此在您的示例中,字段应该是一些vals。;)