Scala:object(单例)

本文详细介绍了Scala中的单例模式实现方法,包括如何定义单例对象及与类的交互方式,并通过具体示例展示了Scala单例模式的工作原理及编译后的类文件结构。

Scala开篇(目录)

使用Java的同学,对单例模式应该很熟悉了,在类的内部声明一个private static 的自身类型的对象,然后通过一个static的方法返回即可。在Scala中,是没有static这个东西的,但是它也为我们提供了单例模式的实现方法,那就是 object(别混了,不是万物之根的object)
Scala中使用单例模式时,除了定义的类之外,还要定义一个同名的object对象,它和类的区别是,object对象不能带参数,先看一段实现代码

/**这是我们定义的类
构造函数被我们定义为private的,防止直接调用该类的构造来创建对象
*/
class StaticTest private {
  private def add_(x: Int, y: Int): Int = {
    return x + y
  }

  private def sub_(x: Int, y: Int): Int = {
    return x + y
  }
}

/**这个就是单例模式的定义,和类同名,且不带参数*/
object StaticTest{
//内部声明一个StaticTest类实例对象
  val singleObj = new StaticTest
  //applay方法,当执行 StaticTest() 时被执行
  def apply()={
    println("-------apply--------")
  }
  def add(x:Int,y:Int):Int={
  //调用StaticTest 类的方法
    return singleObj.add_(x,y)
  }
  //调用StaticTest 类的方法
  def sub(x:Int,y:Int):Int ={
    return singleObj.sub_(x,y)
  }
}

使用

    //定义一个单例对象
    val test = StaticTest
    //调用add方法
    println(test.add(2,3))           //  5

这个类编译后,会生成两个文件StaticTest.class和StaticTest$.class,class和object被编译到了一起
我们看一下StaticTest$.class类的反编译结果,和我们的Java的单例模式就非常相似了。

public final class StaticTest$
{
//指向自己,外部都通过MODULE$访问接口
  public static final  MODULE$;
  //自身类型的内部静态变量
  private final StaticTest singleObj;

  static
  {
    new ();
  }

//这个就是对外接口,返回单例对象,很像我们经常用的getInstance
  public StaticTest singleObj()
  {
    return this.singleObj;
  }
  public int apply() { Predef..MODULE$.println("-------apply--------");
    return add(3, 4); }

  public int add(int x, int y) {
    return singleObj().scala$test$StaticTest$$add_(x, y);
  }
  public int sub(int x, int y) {
    return singleObj().scala$test$StaticTest$$sub_(x, y);
  }
  //私有的构造
  private StaticTest$() {
    //指向自己
    MODULE$ = this;
    //创建对象
    this.singleObj = new StaticTest();
  }
}

再看看StaticTest.class的反编译结果

public class StaticTest
{
  public static int sub(int paramInt1, int paramInt2)
  {
    return StaticTest..MODULE$.sub(paramInt1, paramInt2);
  }

  public static int add(int paramInt1, int paramInt2)
  {
    return StaticTest..MODULE$.add(paramInt1, paramInt2);
  }

  public static void apply()
  {
    StaticTest..MODULE$.apply();
  }

  public static StaticTest singleObj()
  {
    return StaticTest..MODULE$.singleObj();
  }

  public int scala$test$StaticTest$$add_(int x, int y)
  {
    return x + y;
  }

  public int scala$test$StaticTest$$sub_(int x, int y) {
    return x + y;
  }
}

这里都是static方法,方法内通过MODULE$去访问接口

上面是在单例中访问同名类实例中的方法,那如果在单例中有一个类,在外部类中要使用该怎样呢?

class StaticTest private {
  def getInner() : Inner = {
    new Inner
  }
}
object StaticTest{
  class Inner{

  }
}

我们要在类StaticTest中使用单例StaticTest中的Inner类,按照上面的代码,是会提示错误的,提示你找不到Inner类,要想使用它,可以按照下面的方式:
方式一:

//类的外部引入
import scala.test.StaticTest.Inner
class StaticTest private {
  def getInner() : Inner = {
    new Inner
  }
}
object StaticTest{
  class Inner{

  }
}

方式二:

class StaticTest private {
//在类的内部引用
  import StaticTest._
  def getInner() : Inner = {
    new Inner
  }
}
object StaticTest{
  class Inner{

  }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

bdmh

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值