Kotlin 单例,Kotlin伴侣对象

时间:2020-02-23 14:37:32  来源:igfitidea点击:

在本教程中,我们将研究Kotlin如何处理Singleton Pattern和静态属性。
我们将学习如何创建Kotlin Singleton类以及什么是伴随对象。

Kotlin Singleton类

Singleton是一种软件设计模式,可以确保一个类只有一个实例,并且该类提供了对其的全局访问点。

单例模式可确保仅创建一个实例,并将其用作单个访问点,从而确保线程安全。
以下是在Java中创建Singleton类的通用方法。

public class Singleton {
 
  private static Singleton instance = null;
 
  private Singleton(){
  }
 
  private synchronized static void createInstance() {
      if (instance == null) {
          instance = new Singleton();
      }
  }
 
  public static Singleton getInstance() {
      if (instance == null) createInstance();
      return instance;
  }

}

关键字synchronized确保创建实例时没有线程干扰。

上面代码的Kotlin等效项如下所示。

object Singleton

是的,就是在Kotlin中创建单例程序。

Kotlin对象声明

  • Kotlin对Singleton类的表示只需要使用object关键字。

  • 因此,可以在不使用类的情况下定义Kotlin中的Singleton类。

  • "对象"类可以包含属性,函数和" init"方法。

  • 不允许使用构造方法。

  • 可以在类内部定义单例对象。
    不能在内部类中定义。

  • 不能以实例化类的方式实例化对象。

  • 首次使用对象时,将实例化该对象。

让我们看看Kotlin中一个object对象的基本实现。

object Singleton

fun main(args: Array<String>) {
  print(Singleton.javaClass)
}

//Following is printed in the console.
//class Singleton

" javaClass"由单例类自动生成,并打印与Java类名称相同的名称。

让我们在" object"单例类中添加一个函数和属性。

object Singleton
{

  init {
      println("Singleton class invoked.")
  }
  var name = "Kotlin Objects"
  fun printName()
  {
      println(name)
  }

}

fun main(args: Array<String>) {
  Singleton.printName()
  Singleton.name = "KK"

  var a = A()
}

class A {

  init {
      println("Class init method. Singleton name property : ${Singleton.name}")
      Singleton.printName()
  }
}

//Following is printed in the console.
//Singleton class invoked.
//Kotlin Objects
//Class init method. Singleton name property : KK
//KK

在上面的代码中,对象类的更改在实例化类A时反映出来。

对象初始化类似于kotlin属性的惰性初始化。
在下面的代码中,由于未使用"对象",因此未对其进行初始化。

class A {

  object Singleton
  {

      init {
          println("Singleton class invoked.")
      }
      var name = "Kotlin Objects"
      fun printName()
      {
          println(name)
      }

  }

  init {
      println("Class init method. Singleton name property")
  }
}

//Console:
//Class init method

对象不仅仅是单例类,还有更多使用对象。

Kotlin对象表达式

Kotlin中的对象可用作类的变体。
一个对象可以扩展一个类,实现一个接口。

让我们看一下扩展对象中的类以创建变体。

fun main(args: Array<String>) {
  var a = A()
  Singleton.printName()
}

open class A {

  open fun printName() {
      print("This is class A")
  }

  init {
      println("Class init method.")
  }
}

object Singleton : A() {

  init {
      println("Singleton class invoked.")
  }

  var name = "Kotlin Objects"
  override fun printName() {
      println(name)
  }
}

//Console Output:
//Class init method.
//Class init method.
//Singleton class invoked.
//Kotlin Objects

我们将类和函数printName()定义为open,因为它们将分别被子类化和覆盖。

无疑,该类的" init"函数被调用了两次。
因此,我们能够使用上述方法在Kotlin中创建一个匿名类。

对象可以具有超类。

Kotlin伴侣对象

  • Kotlin没有static关键字。
    那么我们如何设置静态变量和方法呢?

  • 伴侣对象就是答案。
    它等效于Java中的"静态"对象。

  • 类对象的所有实例都具有"伴侣对象"。
    它也可以访问该类的所有成员,包括私有构造函数。

  • 实例化类时,将初始化一个伴随对象。

  • 不能在类外部声明伴随对象。

让我们看一个简单的kotlin随播对象示例。

fun main(args: Array<String>) {

  var a = A.name
  A.name = "Kotlin Tutorials"
  A.printName() //prints Kotlin Tutorials
}

class A {

  companion object Singleton
  {

      init {
          println("Singleton class invoked.")
      }
      var name = "Kotlin Objects"
      fun printName()
      {
          println(name)
      }

  }

  init {
      println("Class init method.")
  }
}

通过使用类名称作为限定符来调用伴随对象的成员。

我们也可以省略伴随对象的名称。
在这种情况下,可以使用"同伴"名称来调用Singleton对象。

fun main(args: Array<String>) {

  
  A.Companion
  A.Companion.name = "Kotlin Tutorials"
  A.printName() //prints Kotlin Tutorials
}

class A {

  companion object
  {

      init {
          println("Singleton class invoked.")
      }
      var name = "Kotlin Objects"
      fun printName()
      {
          println(name)
      }

  }

  init {
      println("Class init method.")
  }
}

注意:"对象"在被调用之前不会实例化。
一旦类如下面的代码所示,实例对象就会被实例化。

fun main(args: Array<String>) {
  var a = A()
}

class A {

  companion object SingletonB {

      init {
          println("SingletonB class invoked.")
      }

  }

  object SingletonA {

      init {
          println("SingletonA class invoked.")
      }
  }

  init {
      println("Class init method.")
  }
}

//Following is printed in the console.
//SingletonB class invoked.
//Class init method.

请注意,没有调用"对象"的初始化。