In Kotlin, is it possible to have a factory function that creates an instance of a class with a private constructor?
My goal is to enforce the factory function to be used and to prevent instantiation via the class's constructor.
Example:
// factory function, valid
val myInstance = myClassOf()
// class instantiation, invalid
val myInstance = MyClass()
I'm trying to mimic the behavior of some of the built-in factory functions like intArrayOf()
, e.g.
// works
val myIntArray = intArrayOf()
// not possible as IntArray has a private constructor
val myIntArray = IntArray()
Here the constructor will use the private modifier. The above code is the basic syntax for implementing the private constructor like nothing but the singleton pattern used to call the class attributes. Kotlin Instance() method is used to call and execute the private constructor object.
To do so you need to declare a secondary constructor using the constructor keyword. If you want to use some property inside the secondary constructor, then declare the property inside the class and use it in the secondary constructor. By doing so, the declared variable will not be accessed inside the init() block.
Purpose. Just like Builder, the Factory is a creational pattern. It describes an interface used to deliver instances. Instead of calling object constructor, we can call a method of the Factory which will generate interface implementation - the concrete object.
Private constructors are used to prevent creating instances of a class when there are no instance fields or methods, such as the Math class, or when a method is called to obtain an instance of a class. If all the methods in the class are static, consider making the complete class static.
You can use companion object in this way:
class MyClass private constructor() {
companion object {
operator fun invoke() = MyClass()
}
}
val myInstance = MyClass() // Calls the factory function invoke()
Name the factory function if it has a special meaning. For example:
class MyClass private constructor(values: List<String>) {
companion object {
fun of(vararg values: String) = MyClass(values.toList())
}
}
val myInstance = MyClass.of("first", "second")
You can do something like this:
import MyClass.Companion.myClassOf
class MyClass private constructor() {
companion object {
fun myClassOf() = MyClass()
}
}
//val myInstance1 = MyClass() // not allowed
val myInstance2 = myClassOf()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With