Singleton class in Kotlin

后端 未结 8 1845
梦如初夏
梦如初夏 2020-12-14 13:47

I want to know way to create singleton class, so that my Util class instantiate only once per app. However when I converted my Java class to kotlin, below code was generated

相关标签:
8条回答
  • 2020-12-14 14:29
     class TestMySingleton private constructor() {
    ​
       companion object {
            var single = TestMySingleton()
    
            fun getInstance(): TestMySingleton {
                if (single == null)
                    single = TestMySingleton()
                return single
            }
        }
    
    }
    
    0 讨论(0)
  • 2020-12-14 14:29
    class MyClass {
    
    
        init {
            println("init is called")
        }
    
        companion object {
    
            private var obj: MyClass? = null
            fun getInstance(): MyClass {
                if (obj == null) {
                    obj = MyClass()
                }
                return obj as MyClass 
            }
    
        }
    
        fun printHello() {
            println("Hello World")
        }
    

    You can create its instance by MyClass.getInstance() something like java

    0 讨论(0)
  • 2020-12-14 14:31

    In Kotlin you should get rid of the whole notion of the utility singleton class. The idiomatic way is to simply move all declarations to the top level.

    Java:

    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);
        }
    }
    

    Usage:

    String vin = UTIL.extractVin("aoeuVN14134230430")
    

    In Kotlin just create a separate file called util.kt with the following:

    var prefixLength = 4
    
    fun String.extractVin() = this.substring(prefixLength)
    

    Usage:

    val vin = "aoeuVN14134230430".extractVin()
    

    But... you're polluting the top-level namespace!

    If your Java intuition triggers a red flag here, simply remember that the package is the namespacing construct and as opposed to Java, Kotlin doesn't conflate the concerns of namespacing and encapsulation. There's no "package-private" access level so you're free from the burden of deciding that something must stay within the same package so it can be made package-private.

    So, where in Java you create a degenerate class as a workaround, in Kotlin you just create a file in its own package.

    0 讨论(0)
  • 2020-12-14 14:36

    Super simple lazy example:

    companion object {
        val instance: UtilProject by lazy { UtilProject() }
    }
    
    0 讨论(0)
  • 2020-12-14 14:41

    Just

    companion object {
        val instance = UtilProject()
    } 
    

    will do the job because the companion object itself is a language-level singleton.
    (The instance will be assigned when the companion object is first called.)

    -- Updated --

    If you need to adjust when the singleton object should be initilized, you can create one object for each class.

    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's companion object is instantiated.
        val c = AnotherClass.instance
    }
    

    Here, AnotherClass.instance is initialized before AnotherClass.instance is actually called. It is initialized when AnotherClass's companion object is called. To prevent being initialized before when needed, you can use like this:

    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.
    }
    

    If you don't care when each singleton is initialized, you can also use like this:

    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 
    }
    

    In summary,
    an object or a companion object is one singleton object in Kotlin.
    You can assign variables in an object or objects, and then use the variables just like they were singletons.

    object or companion object is instantiated when it is first used. vals and vars in an object are initialized when the object is first instantiated (i.e., when the object is first used).

    0 讨论(0)
  • 2020-12-14 14:42

    Only the word object is needed.

    object UtilProject {
        var bar: Int = 0
        fun foo() {        
        }
    }
    

    And you directly access the object that has only one instance

    fun main(args: Array<String>) {
        UtilProject.bar = 1
        println(UtilProject.bar)    
    }
    
    0 讨论(0)
提交回复
热议问题