【问题标题】:Understanding Some and Option in Scala理解 Scala 中的一些和选项
【发布时间】:2018-04-20 15:17:50
【问题描述】:

我正在从他们的docs 阅读这个例子:

class Email(val username: String, val domainName: String)

object Email {
  def fromString(emailString: String): Option[Email] = {
    emailString.split('@') match {
      case Array(a, b) => Some(new Email(a, b))
      case _ => None
    }
  }
}

println(Email.fromString("scala.center@epfl.ch"))
val scalaCenterEmail = Email.fromString("scala.center@epfl.ch")
scalaCenterEmail match {
  case Some(email) => println(
    s"""Registered an email
       |Username: ${email.username}
       |Domain name: ${email.domainName}
     """)
  case None => println("Error: could not parse email")
}

我的问题:

  1. 什么是SomeOption

  2. 什么是工厂方法(只是一些创建新对象并返回它的函数?)

  3. 伴生对象有什么意义?它只是包含对所有类实例都可用的函数吗?它们像 Ruby 中的类方法吗?

【问题讨论】:

  • Factory 是一种设计模式,并不特定于 Scala。关于剩下的问题,有几本关于scala的好书和教程,随便搜索:stackoverflow.com/questions/609744/…danielwestheide.com/blog/2012/12/19/…
  • 选项是一个Algebraic Data Type,在函数式编程中,函数被设计为不会将函数破坏为错误,而是安全/一致地返回相同类型的数据,以便您稍后处理它,更多关于@ 987654325@。就像在 Int 中一样,您可以在 Option 中返回值 ...-2323,...,1,2,3... 如果成功则返回 Some ,如果失败则返回 None 。
  • 如果您有多个问题,请提出多个问题。特别是,我们的三个问题中的每一个都已经在Stack Overflow 上被多次询问和回答,但是使用内置的重复系统不可能指出这些问题,因为您的问题将它们混合在一起。 Stack Overflow 的重要特征之一是可以通过多个不同的问题获取知识,但您的问题会破坏该系统。
  • 您不应该阅读一个好的介绍/教程,而不是阅读您不理解的文档并运行任何 Scala 初学者都可以回答的问题吗?

标签: scala


【解决方案1】:

什么是一些和选项?

Option 是一种表示可选性的数据结构,顾名思义。每当计算可能不返回值时,您都可以返回OptionOption 有两种情况(表示为两个子类):SomeNone

在上面的示例中,方法Email.fromString 可能会失败并且不会返回值。这用Option 表示。为了知道计算是否产生了值,您可以使用match 并检查它是Some 还是None

Email.fromString("scala.center@epfl.ch") match {
  case Some(email) => // do something if it's a Some
  case None => // do something it it's a None
}

这比返回null 要好得多,因为现在调用该方法的人不可能忘记检查返回值。

例如比较这个:

def willReturnNull(s: String): String = null

willReturnNull("foo").length() // NullPointerException!

有了这个

def willReturnNone(s: String): Option[String] = None

willReturnNone("foo").length() // doesn't compile, because 'length' is not a member of `Option`

另外,请注意,使用match 只是使用Option 的一种方式。进一步的讨论将涉及使用mapflatMapgetOrElse 或在Option 上定义的类似方法,但我觉得这里会离题。

什么是工厂方法(只是一些创建新对象并返回它的函数?)

这不是 Scala 特有的。 “工厂方法”通常是构造某种类型的值的静态方法,可能隐藏类型本身的细节。在这种情况下,fromString 是一个工厂方法,因为它允许您创建一个 Email 而无需使用 new Email(...) 调用 Email 构造函数

伴生对象有什么意义?它只是包含对所有类实例都可用的函数吗?它们像 Ruby 中的类方法吗?

作为第一个近似值,是的。 Scala 没有类的静态成员。相反,您可以将object 与该类关联,您可以在其中定义所有静态内容。

例如在 Java 中你会:

public class Email {
   public String username;
   public String domain;
   public static Optional<Email> fromString(String: s) {
      // ...
   }
}

在 Scala 中,您可以大致定义相同的类:

class Email(val username: String, val domain: String)
object Email {
  def fromString(s: String): Option[Email] = {
    // ...
  }
}

【讨论】:

  • 这比返回 null 要好得多,因为现在调用该方法的人不可能忘记检查返回值。 谢谢。这正是我所需要的。
【解决方案2】:

我想在第三个问题中添加一些示例/信息。

如果你在伴生对象中使用akka,你可以将你使用的每条消息放在case方法中(它应该继续并由actor使用)。此外,您可以为演员的名称或其他常量值添加一些 val。

如果您使用 JSON,您应该为其创建格式(有时是自定义读取和写入)。您应该将此格式放入伴随对象中。也可以创建实例。

如果您更深入地了解 Scala,您可以找到 case classes。因此,在没有new 的情况下创建此类对象的可能性是因为“默认”companion object 中有一个方法 apply。

但总的来说,这是一个可以放置所有“静态”方法等的地方。

关于Option,它为您提供了避免某些异常并在您没有​​任何值时做出某些事情的可能性。 Gabriele 举了一个电子邮件的例子,所以我再添加一个。 您有一个发送电子邮件的方法,但您从User 类接收电子邮件。用户可以让这个字段为空,所以如果我们有类似的东西 val maybeEmail: Option[String] = user.email 您可以使用例如地图发送电子邮件 maybeEmail.map(email =&gt; sendEmail(email))

因此,如果您使用它,在编写上述方法时,您无需考虑用户是否指定了他的电子邮件:)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-08-10
    • 1970-01-01
    • 2020-03-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-14
    相关资源
    最近更新 更多