Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Kotlin - Factory Function for Class with Private Constructor

Tags:

kotlin

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()
like image 759
Pooch Avatar asked Aug 03 '17 19:08

Pooch


People also ask

How do you make a private constructor in Kotlin?

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.

How do I create a secondary constructor in Kotlin?

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.

What is Factory function in Kotlin?

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.

What is the benefit of private constructor?

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.


2 Answers

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")
like image 67
Haim Avatar answered Oct 16 '22 04:10

Haim


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()
like image 34
JK Ly Avatar answered Oct 16 '22 05:10

JK Ly