单身人士与科特林的争论

时间:2015-10-14 14:25:05

标签: kotlin

Kotlin reference表示我可以使用 object 关键字创建单例,如下所示:

object DataProviderManager {
  fun registerDataProvider(provider: DataProvider) {
    //
  }
}

但是,我想将一个参数传递给该对象。例如,Android项目中的ApplicationContext。

有办法做到这一点吗?

6 个答案:

答案 0 :(得分:14)

由于对象没有构造函数,因此我在以下步骤中将值注入初始设置。你可以随意调用函数,可以随时调用它来修改值(或根据你的需要重建单例)。

object Singleton {
    private var myData: String = ""

    fun init(data: String)  {
        myData = data
    }

    fun singletonDemo() {
        System.out.println("Singleton Data: ${myData}")
    }
}

答案 1 :(得分:4)

Kotlin有一个名为Operator overloading的功能,允许您将参数直接传递给对象。

object DataProviderManager {
  fun registerDataProvider(provider: String) {
      //
  }

  operator fun invoke(context: ApplicationContext): DataProviderManager {
      //...
      return this
  }
}

//...
val myManager: DataProviderManager = DataProviderManager(someContext)

答案 2 :(得分:2)

还有两个本机Kotlin注入库非常容易使用,并且有其他形式的单例,包括每个线程,基于密钥等。不确定是否在您的问题的上下文中,但这里是两者的链接:

通常在Android中,人们使用像这样的库,或者Dagger等人来完成单例参数化,范围化等等。

答案 3 :(得分:1)

我建议您使用这种形式在Kotlin的Siglot中传递参数,以借记您的构造函数的对象被剥夺并被阻止:

object Singleton {

fun instance(context: Context): Singleton {
    return this
}

fun SaveData() {}

}

您在活动中这样称呼

Singleton.instance(this).SaveData()

答案 4 :(得分:1)

使用大多数现有答案,就可以访问类成员而无需先初始化单例。这是一个线程安全的示例,可以确保在访问其任何成员之前创建一个实例。

class MySingleton private constructor(private val param: String) {

    companion object {
        @Volatile
        private var INSTANCE: MySingleton? = null

        @Synchronized
        fun getInstance(param: String): MySingleton = INSTANCE ?: MySingleton(param).also { INSTANCE = it }
    }

    fun printParam() {
        print("Param: $param")    
    }
}

用法:

MySingleton.getInstance("something").printParam()

答案 5 :(得分:0)

如果您正在寻找具有多个参数的基本 SingletonHolder 类。我创建了 SingletonHolder 泛型类,该类支持仅创建带有一个参数、两个参数和三个参数的单例类的一个实例。

link Github of the base class here

非参数(Kotlin 的默认设置):

def network_fn(obs):
    f_output = 128
    g_output = 128
    node_embeddings = obs
    
    # layer g
    G = tf.keras.layers.Dense(units=g_output,
                          use_bias=True,
                          kernel_initializer=ortho_init(np.sqrt(2)),
                          bias_initializer=tf.constant_initializer(0.0),
                          activation=None,
                          name="g")
    # layer f
    f = tf.keras.layers.Dense(units=f_output,
                          use_bias=True,
                          kernel_initializer=ortho_init(np.sqrt(2)),
                          bias_initializer=tf.constant_initializer(0.0),
                          activation=None,  
                          name="f_%i" % edge_type_idx))

    f_output = f(node_embeddings)
    f_output = tf.nn.tanh(f_output)

    G_input = tf.concat([node_embeddings, f_output], axis=-1)

    G_output = G(G_input)
    G_output = tf.nn.tanh(G_output)
    return G_output

一个参数(来自上面链接中的示例代码):

object AppRepository 

两个参数:

class AppRepository private constructor(private val db: Database) {
    companion object : SingleArgSingletonHolder<AppRepository, Database>(::AppRepository)
}
// Use
val appRepository =  AppRepository.getInstance(db)

三个参数:

class AppRepository private constructor(private val db: Database, private val apiService: ApiService) {
    companion object : PairArgsSingletonHolder<AppRepository, Database, ApiService>(::AppRepository)
}
// Use
val appRepository =  AppRepository.getInstance(db, apiService)

超过 3 个参数:

为了实现这种情况,我建议创建一个配置对象来传递给单例构造函数。