[译]Scala单例对象

不属于单个实例的方法和值属于单例对象,用关键字object而不用class来标记。

package test

object Blah {
  def sum(l: List[Int]): Int = l.sum
}

这个sum方法是全局可用的,并且可以用test.Blah.sum来引用或引入。

单例对象某种程度来说是定义一个单一使用类,不能直接实例化,并且在object定义处有一个同名的val成员。实际上,像val,单例对象可以被定义为一个特征或类的成员,虽然这不是典型用法。

单例对象可以扩展类和特征。实际上,不带type parametersCase类会默认创建一个同名的单例对象,实现了特征[Function*]。

伴生

大部分单例对象不是独立的,而是和相同名字的类关联。前面提到的Case类的同名单例对象,就是一个例子。这种情况下,单例对象被称为类的伴生对象(companion object),类称为对象的伴生类(companion class)

Scaladoc对类和其伴生对象之间跳转做了特殊支持:可以点击大的"C"或者"O"圆圈图标跳转到伴生对象。

class IntPair(val x: Int, val y: Int)

object IntPair {
  import math.Ordering
  implicit def ipord: Ordering[IntPair] =
    Ordering.by(ip => (ip.x, ip.y))
}

看到typeclass示例作为implicit values是很常见的,如上面的在伴生中定义的ipord。这是因为伴生成员包含在相关值的默认隐式搜索中。

给Java程序员提示

Scala中static不是一个关键字。相反,所有成员都是静态的,包括类,都应该归为单例对象。它们可以用相同的语法引用,单独或者作为一个整体被引入等等。

Java程序员会频繁定义静态成员,也许是private的,作为实例成员的辅助实现。这些都转为使用伴生对象,一种常用模式是在类中引入伴生对象的成员。如下:

class X {
  import X._

  def blah = foo
}

object X {
  private def foo = 42
}

这种使用方式展现了另外一个特性:在private上下文中,类和它的伴生对象是友元。object X可以访问class X的私有成员,反之亦然。想要有真正的私有成员,使用private[this]

为了给Java提供方便,在单例对象中直接定义的方法(包括varval)也会在伴生类中定义静态方法,叫做static forwarder。对于object X,其它成员可以用X$.MODULE$静态字段访问。如果你把所有实现都放在伴生对象中并且发现就剩下一个不用实例化的类了,那就把类删掉。static forwarder仍然会被创建。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 32,189评论 18 399
  • 前言 人生苦多,快来 Kotlin ,快速学习Kotlin! 什么是Kotlin? Kotlin 是种静态类型编程...
    任半生嚣狂阅读 26,453评论 9 118
  • 单例模式(SingletonPattern)一般被认为是最简单、最易理解的设计模式,也因为它的简洁易懂,是项目中最...
    成热了阅读 9,854评论 4 34
  • w3school上的W3C简介 W3C指万维网联盟(World Wide Web Consortium), W3C...
    不是我的简书阅读 6,579评论 0 0
  • 慢悠悠的骨头 卡住了喉咙 我高声呼喊 带着结实的声音 一千年过去了 流氓的蝴蝶 摒弃北风 我一直奇怪自己曾停留在这...
    留子尧阅读 1,566评论 3 5