美文网首页Scala Tour
[译]Scala单例对象

[译]Scala单例对象

作者: steanxy | 来源:发表于2017-05-07 17:34 被阅读261次

    不属于单个实例的方法和值属于单例对象,用关键字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仍然会被创建。

    相关文章

      网友评论

        本文标题:[译]Scala单例对象

        本文链接:https://www.haomeiwen.com/subject/tqtptxtx.html