2016-06-24 9 views
11

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

Ситуация 1

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

Ситуация 2

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

Ситуация 3

fun doSomething() {} 

Bytecode Результат

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

Мои вопросы:

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

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

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

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

+0

Может быть, это может быть помощи {http://stackoverflow.com/q/37794850/2804610} – EPadronU

+0

В rega rds к вашему последнему абзацу, я думаю, что этот ответ мог бы помочь вам {http://stackoverflow.com/a/37944990/2804610} – EPadronU

ответ

3

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

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"))); 
} 
+3

Почему бы не позвонить напрямую из класса «Цвет»? 'Println (Color.findById (Color.valueOf ("красный")));' – UnKnown

8

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

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

5

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

Обратите внимание, что 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)