Singleton класс в Котлине
Я хочу знать способ создания singleton-класса, так что мой класс Util создается только один раз для каждого приложения. Однако, когда я преобразовал свой Java-класс в kotlin, под кодом был создан.
Это правильно?
companion object {
private var utilProject: UtilProject? = null
val instance: UtilProject
get() {
if (utilProject == null) utilProject = UtilProject()
return utilProject!!
}
}
Я мог бы найти связанный с этим вопрос, но это параметр, и я не получаю его без параметров.
Ответы
Ответ 1
Просто
companion object {
val instance = UtilProject()
}
будет выполнять эту работу, потому что сам объект-компаньон является одноэлементным языком.
(instance
будет назначен при первом вызове сопутствующего объекта.)
- Обновлено -
Если вам нужно настроить, когда объект singleton должен быть инициализирован, вы можете создать один объект для каждого класса.
class UtilProject {
....
companion object {
val instance = UtilProject()
}
}
class AnotherClass {
...
companion object {
val instance = AnotherClass()
const val abc = "ABC"
}
}
fun main(args: Array<String>) {
val a = UtilProject.instance // UtilProject.instance will be initialized here.
val b = AnotherClass.abc // AnotherClass.instance will be initialized here because AnotherClass companion object is instantiated.
val c = AnotherClass.instance
}
Здесь AnotherClass.instance
инициализируется до AnotherClass.instance
как на самом деле AnotherClass.instance
. Он инициализируется при AnotherClass
сопутствующего объекта AnotherClass
. Чтобы предотвратить инициализацию до того, когда это необходимо, вы можете использовать следующее:
class UtilProject {
....
companion object {
fun f() = ...
}
}
class AnotherClass {
...
companion object {
const val abc = "ABC"
}
}
object UtilProjectSingleton {
val instance = UtilProject()
}
object AnotherClassSingleton {
val instance = AnotherClass()
}
fun main(args: Array<String>) {
UtilProject.f()
println(AnotherClass.abc)
val a = UtilProjectSingleton.instance // UtilProjectSingleton.instance will be initialized here.
val b = AnotherClassSingleton.instance // AnotherClassSingleton.instance will be initialized here.
val c = UtilProjectSingleton.instance // c is a.
}
Если вам не все равно, когда каждый синглтон инициализирован, вы также можете использовать:
class UtilProject {
....
companion object {
fun f() = ...
}
}
class AnotherClass {
...
companion object {
const val abc = "ABC"
}
}
object Singletons {
val utilProject = UtilProject()
val anotherClass = AnotherClass()
}
fun main(args: Array<String>) {
val a = Singletons.utilProject
val b = Singletons.anotherClass
}
В итоге,
object
или companion object
является одним одноэлементным объектом в Котлине.
Вы можете назначать переменные в объекте или объектах, а затем использовать переменные так же, как они были одиночными.
object
или companion object
создается при его первом использовании. val
и var
в object
инициализируются при первом экземпляре object
(т.е. когда object
сначала используется).
Ответ 2
В Kotlin есть специальное ключевое слово object
для синглетонов. Вы можете просто напечатать что-нибудь простое, чтобы получить рабочий одноэлементный класс:
object MySingleton
или когда вам нужны некоторые функции-члены:
object MySingleton {
fun someFunction(...) {...}
}
А затем используйте его:
MySingleton.someFunction(...)
есть ссылка: https://kotlinlang.org/docs/reference/object-declarations.html#object-declarations
EDIT:
В вашем случае вам просто нужно заменить в своем определении class UtilProject
следующее:
object UtilProject {
// here you put all member functions, values and variables
// that you need in your singleton Util class, for example:
val maxValue: Int = 100
fun compareInts(a: Int, b: Int): Int {...}
}
И тогда вы можете просто использовать свой синглтон в других местах:
UtilProject.compareInts(1, 2)
//or
var value = UtilProject.maxValue
Ответ 3
Супер простой ленивый пример:
companion object {
val instance: UtilProject by lazy { UtilProject() }
}
Ответ 4
В Kotlin вы должны избавиться от всего понятия утилиты синглтон-класса. Идиоматический способ - просто переместить все объявления на верхний уровень.
Джава:
public final class Util {
public static final Util UTIL = new Util();
private int prefixLength = 4;
private Util() {}
public void setPrefixLength(int newLen) {
prefixLength = newLen;
}
public String extractVin(String input) {
return input.substring(prefixLength);
}
}
Использование:
String vin = UTIL.extractVin("aoeuVN14134230430")
В Kotlin просто создайте отдельный файл с именем util.kt
со следующим:
var prefixLength = 4
fun String.extractVin() = this.substring(prefixLength)
Использование:
val vin = "aoeuVN14134230430".extractVin()
Но... вы загрязняете пространство имен верхнего уровня!
Если ваша интуиция Java вызывает здесь красный флаг, просто помните, что пакет является конструкцией пространства имен, и в отличие от Java, Kotlin не разделяет проблемы пространства имен и инкапсуляции. Нет никакого уровня доступа "пакетный приватный", так что вы освобождаетесь от необходимости решать, что что-то должно оставаться в одном пакете, чтобы его можно было сделать пакетным.
Итак, если в Java вы создаете вырожденный класс в качестве обходного пути, в Kotlin вы просто создаете файл в своем собственном пакете.
Ответ 5
Требуется только объект слова.
object UtilProject {
var bar: Int = 0
fun foo() {
}
}
И вы напрямую обращаетесь к объекту, который имеет только один экземпляр
fun main(args: Array<String>) {
UtilProject.bar = 1
println(UtilProject.bar)
}
Ответ 6
Пример Singleton
по модернизации для поддержки вызова API.
object RetrofitClient {
private var instance: Api? = null
private val BASE_URL = "https://jsonplaceholder.typicode.com/"
fun getInstance(): Api? {
if (instance == null) {
val retrofit = Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build()
instance = retrofit.create(Api::class.java)
}
return instance
}
}