Объект Kotlin vs companion-object vs package методы

Я написал эти методы в Котлине и проанализировал байт-код:

Ситуация 1

class A {
    object b {
        fun doSomething() {}
    }
}

Ситуация 2

class A {
    companion object b {
        fun doSomething() {}
    }
}

Ситуация 3

fun doSomething() {}

Результат байткода

  • Ситуация 1: Test$asb класса Test$asb, public final doSomething()I
  • Ситуация 2: Test$Companion класса Test$Companion, public final doSomething()I
  • Ситуация 3: класс TestKt, public final static doSomething()I

Мои вопросы:

  • У меня есть класс enum, и я хочу вернуть enum instace с переменной enum, например findById (enum(id, color)). Как мне это сделать? Сопутствующий объект? объект?

  • Кажется, единственный способ иметь реальный статический метод на уровне пакета, без объявления класса. Но это становится немного слишком глобальным. Есть ли способ получить к нему доступ через: ClassName.staticMethod, staticMethod действительно статичен.

  • Предоставьте значащие примеры методов объявления пакета, объекта и объекта сопутствующих объектов.

Контекст. Я кодировал в Котлине, и я нахожу это удивительным. Но иногда мне нужно принять решение: например, тяжелое неизменяемое свойство, которое в java я объявляю статичным окончательным, но в Котлине мне трудно "найти эквивалент".

Ответ 1

Я бы предложил разработать воддан ответ:

enum class Color {

    RED,
    BLUE,
    GREEN;


    companion object Utils {
        fun findById(color: Color): Color {
            return color;
        }
    }
}

И проверить

@Test
fun testColor() {
    println(Color.Utils.findById(Color.valueOf("RED")));
}

Ответ 2

Если у вас есть функция, которая выполняет некоторые действия, тесно связанные с классом, но не требует экземпляр класса, например, пример findById, вы должны поместить его в объект-компаньон класса.

Если вы хотите выставить метод как статический метод для Java-кода, вы можете аннотировать его с @JvmStatic аннотации @JvmStatic.

Ответ 3

Если функции не требуется экземпляр класса, то это ваше дизайнерское решение, куда его поставить. Используйте уровень пакета, если он специфичен для пакета, используйте компаньона класса, если он близко относится к классу (например, другие классы в пакете имеют схожие функции).

Обратите внимание, что enum имеет несколько встроенных свойств и шаблонов:

enum class Colour(val value: Int) {
    black(100), red(200), green(300)
}

fun colourById(id: Int) = Colour.values[id]
fun colourByValue(value: Int) = Colour.values.first {it.value == value}
fun colourByName(name: String) = Colour.valueOf(name)