在Scala中使用选项的惯用方法

Sam*_*che 5 scala equals options tostring pattern-matching

我正在将一些Java代码转换为Scala,试图尽可能使代码成为惯用语.

所以,我现在有一些使用Options而不是可空值的代码,我想知道是不是scala'ish,或者我是不是错了.所以,你们可以批评下面的代码片段吗?

我特意寻找反馈的领域是:

  • 使用伴随对象作为工厂,根据我们是否要传递Options或Strings提供2个选项:String构造函数是否正常,或者我们是否应该总是暴露它是一个Option的事实?
  • 前置条件的使用:是否有更好的方法来断言alpha3Code和name是必需的,并且必须为alpha2Code传递非null选项?(我在使用Guava获取字符串utils,因为我在Scala API中没有找到任何内容)
  • hashCode,equals和toString的实现.equals和toString再次委托给Guava,而equals使用模式匹配.是否有更加潇洒的方式?
  • 我知道我可以使用Case类,它会创建默认实现,但我最感兴趣的是学习如何在不能使用case类的情况下实现它们.

非常感谢 !

package com.sirika.openplacesearch.api.language

import com.google.common.base.Objects
import com.google.common.base.Strings

object Language {
    def apply(name : String, alpha3Code : String, alpha2Code : Option[String]) = new Language(name, alpha3Code, alpha2Code)
    def apply(name : String, alpha3Code : String, alpha2Code : String = null) = new Language(name, alpha3Code, Option(alpha2Code))
    def unapply(l : Language) = Some(l.name, l.alpha3Code, l.alpha2Code )
}


class Language(val name : String, val alpha3Code : String, val alpha2Code : Option[String]) {
    require(!Strings.isNullOrEmpty(alpha3Code))
    require(!Strings.isNullOrEmpty(name))
    require(alpha2Code != null)

    override def hashCode(): Int = Objects.hashCode(alpha3Code)

            override def equals(other: Any): Boolean = other match {
        case that: Language => this.alpha3Code == that.alpha3Code
        case _ => false
    }

    override def toString() : String = Objects.toStringHelper(this)
        .add("name", name)    
        .add("alpha3", alpha3Code)
        .add("alpha2", alpha2Code)
        .toString()
}
Run Code Online (Sandbox Code Playgroud)

ten*_*shi 4

Option[String]我认为你应该只在工厂方法中公开。例如,作为您库的用户,我也会问自己应该使用哪种工厂方法的问题。我很可能会使用 Option。

Scala 为我们提供了足够的工具来让我们的生活更轻松。例如,您可以使用默认选项,如下所示:

def apply(name: String, alpha3Code: String, alpha2Code: Option[String] = None) = 
 new Language(name, alpha3Code, alpha2Code)
Run Code Online (Sandbox Code Playgroud)

如果我再次作为您的库的用户,只想传递字符串而不Some每次都将其包装起来,我可以编写自己的隐式转换,如下所示:

implicit def anyToOption[T](t: T): Option[T] = Some(t)
Run Code Online (Sandbox Code Playgroud)

甚至(如果我个人使用空值):

implicit def anyToOption[T](t: T): Option[T] = 
 if (t == null) None else Some(t)
Run Code Online (Sandbox Code Playgroud)

但我相信,如果你强制执行选项,它会让你的 API 更加扎实和清晰。

  • 实际上,有一种更简单的方法可以将对象包装在“Option”中,使“null”值变为“None”:“Option(t)”(而不是“Some(t)”) (3认同)