Kotlin - Factory Функция для класса с частным конструктором

В Kotlin возможно ли иметь функцию factory, которая создает экземпляр класса с частным конструктором?

Моя цель - принудительно использовать функцию factory, которая будет использоваться, и предотвратить создание экземпляра через конструктор класса.

Пример:

// factory function, valid
val myInstance = myClassOf()

// class instantiation, invalid
val myInstance = MyClass()

Я пытаюсь имитировать поведение некоторых встроенных функций factory, таких как intArrayOf(), например.

// works
val myIntArray = intArrayOf()

// not possible as IntArray has a private constructor
val myIntArray = IntArray()

Ответ 1

Вы можете сделать что-то вроде этого:

import MyClass.Companion.myClassOf

class MyClass private constructor() {
    companion object {
        fun myClassOf() = MyClass()
    }
}

//val myInstance1 = MyClass() // not allowed
val myInstance2 = myClassOf()

Ответ 2

Вы можете использовать сопутствующий объект следующим образом:

class MyClass private constructor() {
  companion object {
    operator fun invoke() = MyClass()
  }
}

val myInstance = MyClass() // Calls the factory function invoke()

Назовите функцию factory, если она имеет особое значение. Например:

class MyClass private constructor(values: List<String>) {
  companion object {
    fun of(vararg values: String) = MyClass(values.toList())
  }
}

val myInstance = MyClass.of("first", "second")

Ответ 3

Попробуйте вместо этого Builder.

class FoodOrder private constructor(
  val bread: String?,
  val condiments: String?,
  val meat: String?,
  val fish: String?) {

    data class Builder(
      var bread: String? = null,
      var condiments: String? = null,
      var meat: String? = null,
      var fish: String? = null) {

        fun bread(bread: String) = apply { this.bread = bread }
        fun condiments(condiments: String) = apply { this.condiments = condiments }
        fun meat(meat: String) = apply { this.meat = meat }
        fun fish(fish: String) = apply { this.fish = fish }
        fun build() = FoodOrder(bread, condiments, meat, fish)
    }
}

Ссылка: https://www.baeldung.com/kotlin-builder-pattern