探索Scala(3)-- 单例对象

研究一下Scala语言的单例对象(Singleton Objects),为下一篇文章做准备。

static不是关键字

上一篇文章提到过,interface并不是Scala语言关键字,可以自由使用。同样,static在Scala里也没有特殊的含义,也是可以自由使用的,如下面代码所示:

单例对象

Java并不是完美的面向对象语言,包括很多缺陷,比如允许static字段和方法,primitive类型,等等。Scala语言在这些方面都有所改进,所以号称是比Java更OO的语言。既然去掉了static关键字,那么如何像Java语言那样,表达类字段类方法呢?Scala给出的解决方案是:单例对象。Java有一个Math类(java.lang.Math),里头全是static字段和方法,部分代码如下所示:

public final class Math {

    private Math() {} // Don't let anyone instantiate this class.

    public static final double PI = 3.14159265358979323846;

    public static int abs(int a) {
        return (a < 0) ? -a : a;
    }

}

下面我们用Scala语言重写上面的Math类:

单例对象实现方式

下面看看Scala是如何实现单例对象的。观察编译结果可以看到,MyMath被编译出两个class:MyMath.classMyMath$.class。我自己分析了一下这两个class,下面是MyMath.class的反编译结果:

public final class MyMath {

    public static double PI() {
        return MyMath$.MODULE$.PI();
    }

    public static int abs(int a) {
        return MyMath$.MODULE$.abs(a);
    }

}

可以得出如下结论:

  1. val字段实际上也被编译成了方法
  2. 两个方法都是static,而且只是调用MyMath$.MODULE$的相应方法

再来看MyMath$.class的反编译结果:

public final class MyMath$ {

    public static final MyMath$ MODULE$;
    private final double PI;

    static {
        new MyMath$();
    }

    private MyMath$() {
        MyMath$.MODULE$ = this;
        this.PI = 3.14;
    }

    public double PI() {
        return this.PI;
    }

    public int abs(int a) {
        return return (a < 0) ? -a : a;
    }

}

就是普通的单例模式,这肯定也就是单例对象这一名称的由来。

使用单例对象

下面这段代码演示了如何使用单例对象:

看起来和使用Java静态字段或方法没啥区别,下面是反编译之后的main方法代码:

Predef$.MODULE$.println("PI is " + MyMath$.MODULE$.PI())
final int x = -18
final int y = MyMath$.MODULE$.abs(x)

伴随类和伴随对象

上面的例子中,我们定义了名为MyMath的单例对象,实际上,这并不妨碍我们定义同名的。如下所示:

这种情况下,单例对象叫做同名类的Companion Object,类叫做单例对象的Companion Class。如果仅定了单例对象,但没有定义同名的类,那么这种情况下单例对象被叫做Standalone Object

时间: 2024-08-02 12:30:17

探索Scala(3)-- 单例对象的相关文章

Scala的单例对象

通常,一个类对应一个伴生对象,其方法就跟Java中的静态方法一样,举例:BigInt类的BigInt伴生对象有一个生成指定位数的随机素数的方法probablePrime,在REPL中运行下列代码: object HelloWorld{ def main(args:Array[String]){ for( i<- 1 to 10){ println(BigInt.probablePrime(10,scala.util.Random)); } } } 得到的结果如下: 523 977 839 911

【Scala】单例对象与伴生对象

Scala的单例对象 Scala不能定义静态成员,而是代之定义单例对象(singleton object).以object关键字定义. 对象定义了某个类的单个实例,包含了你想要的特性: object Accounts{ private var lastNumber = 0 def newUniqueNumber() = { lastNumber += 1; lastNumber} } 当你在应用程序中需要一个新的唯一账号时,调用Account.newUniqueNumber()即可. 对象的构造

转:【Scala】单例对象与伴生对象

转自:http://blog.csdn.net/jasonding1354/article/details/46507595 Scala的单例对象 Scala不能定义静态成员,而是代之定义单例对象(singleton object).以object关键字定义. 对象定义了某个类的单个实例,包含了你想要的特性: object Accounts{ private var lastNumber = 0 def newUniqueNumber() = { lastNumber += 1; lastNum

Scala学习 -- 单例对象

Scala 比 Java 更面向对象一点,是 Scala 的类不允许静态(static)成员.对此类使用场景,Scala 提供了 单例对象(object).单例对象的定义看上去跟类定义很像,只不过 class 关键字被换成了 object 关键字. 在事例中单例对象名叫 ChecksumAccumulator, 跟前一个例子中的类名一样. 当单例对象跟某个类公用同一个名字时,它被称作这个类的 伴生对象(companion object). 必须在同一个源码文件中定义的类和类的伴生对象.同时,类又

scala学习手记14 - 单例对象

java中的单例模式都很熟悉了:简单地说就是一个类只能有一个实例.在scala中创建单例对象非常简单,创建类时使用object关键字替换class即可.因为单例类无法初始化,所以不能向它的主构造函数传递参数. 下面是一个单例的示例: class Marker(val color: String) { println("Creating " + this) override def toString(): String = "marker color " + colo

Scala 单例对象

环境: CentOS 6.3, eclipse 单例对象:类是指用class定义的scala 对象,如果用object替换class关键字,那么这个就叫单例对象,sigleton object, 单例对象不可以使用new 关键字生成新的对象实例下面使用三种使用校验和的方式来解释大家的疑问. ChecksumAccumulator.scala //定义class(类) ChecksumAccumulator 和其伴生单例对象(object) ChecksumAccumulator package

scala入门-08 apply方法和单例对象的使用

首先 在scala下的 org.scala.clazz下创建UsageOfApply.scala 我们做过Java开发都知道 main方法中的对象都是静态的,而scala object对象的方法都是静态方法 接下来 我们看下 apply是如何使用的 当 val applyTest = new ApplyTest() 会导致apply方法的调用并返回该方法调用的值,也就是ApplyTest的实例化对象 Class中也可以由apply方法,其使用方法如下所示: 由于 object中的方法和属性都是静

JS单例对象与构造函数对象的区别

JavaScript对象有几种: 内置对象如Global,Math对象等等. 本地对象如Object.Function.Array.String.Boolean.Number.Date.RegExp.Error.EvalError.RangeError.ReferenceError.SyntaxError.TypeError.URIError. 然而这跟要说的内容并没有什么关系,正题:曾经(此秒之前)纠结过json对象和构造函数对象有什么关系,区别是什么,该怎么合理使用,今天心情...仔细思考探

010-Scala单例对象、伴生对象实战详解

010-Scala单例对象.伴生对象实战详解 Scala单例对象详解 函数的最后一行是返回值 子项目 Scala伴生对象代码实战 object对象的私有成员可以直接被class伴生类访问,但是不可以被其他的类或者对象访问 伴生类访问伴生对象的成员时,要通过名称.成员来访问 调用一些元素的方法初始化创建的时候,例如:Array(1,2,,34,5,6)其实调用了它的apply()方法 欢迎广大爱好者学习交流.也欢迎广大学习爱好者加入 DT大数据梦工厂交流群:462923555 DT大数据微信公众账