Закрытое статическое поле Java и анонимные внутренние классы против Kotlin const val и объектных выражений / объявлений - PullRequest
0 голосов
/ 03 марта 2019

Допустим, у меня есть интерфейс Kotlin:

interface Dog {
    fun walk()
}

Я хочу создать объект Kotlin этого класса с небольшими изменениями , например:

val poodle : Dog = object : Dog {

    override fun walk() {
        ...
    }
}

Однако я также хочу добавить к этому объекту то, что эквивалентно частному статическому конечному полю в Java, например, ( это рабочий пример в Java ):

Dog poodle = new Dog() {

    private static final String POODLE_FASHION = ...

    @Override
    public walk() {
        ...
    }
}

Я читал, что частный const val эквивалентен этому в Kotlin.Я попытался сделать следующее (это пример в Kotlin, который НЕ работает) :

val poodle : Dog = object : Dog {

    private const val POODLE_FASHION = ...

    override fun walk() {
        ...
    }
}

Когда я сделал это, я получил следующую ошибку в Android Studio: Const 'val' разрешены только на верхнем уровне или в объектах .

Может кто-нибудь объяснить, почему работает версия Java, а версия Kotlin - нет?Как мне сделать это для Kotlin (я уже пробовал объект-компаньон, но получил ошибку Модификатор «companion» не применим внутри «локального класса» )?Обратите внимание, что я не хочу делать следующее, потому что я хочу, чтобы POODLE_FASHION жил внутри val poodle, так как я собираюсь также создавать другие объекты Dog с небольшой модификацией (val pug, val chihuahua и т. Д.):

private const val POODLE_FASHION = ...

val poodle : Dog = object : Dog {

    override fun walk() {
        ...
    }
}

Спасибо!

Ответы [ 2 ]

0 голосов
/ 03 марта 2019

Обратите внимание на разницу между выражением объекта и объявлением объекта.

  • val poodle = object: Dog { ... } - это выражение объекта .Создает анонимный объект.Это эквивалентно написанию Dog poodle = new Dog() { ... } на Java.
  • object Poodle: Dog { ... } - это объявление объекта .Он создает одноэлементный объект и примерно эквивалентен созданию класса Java, который ограничен только одним экземпляром.

В документации Kotlin говорится, что свойства const val должны быть "верхнего уровня", илиэлемент объявления объекта или сопутствующего объекта. "(https://kotlinlang.org/docs/reference/properties.html#compile-time-constants). Они недопустимы в объектных выражениях.

Следующее объявление объекта должно работать нормально:

object Poodle : Dog {
    private const val POODLE_FASHION = ...

    override fun walk() {
        ...
    }
}

Одна важная причина различия состоит в том, что выражение объекта нене объявляйте новый тип (хотя, в терминах Java, это приводит к анонимному классу).

  • val poodle = object: Dog { ... } создает переменную типа Dog. Не существует такого типа, как Poodle.
  • object: Poodle: Dog { ... } создает объект типа Poodle. Это новый тип, который является подтипом Dog.

Это различие важно, потому чтов Kotlin свойство const val всегда принадлежит типу. MyClass.MY_CONST_VAL допустимо, но обращение к нему как MyClass().MY_CONST_VAL является ошибкой и не будет работать. В результате свойство const val анонимного объекта всегда будетфактически закрытый для этого объекта.

Я не вижу технической причины, по которой невозможно разрешить const val свойства анонимным объектам (static final постоянные поля времени компиляции разрешены во внутреннем Javaклассы), но их полезностьбудет строго ограничен, и это просто не будет частью спецификации языка Kotlin.

0 голосов
/ 03 марта 2019
val poodle : Dog = object : Dog {

    private const val POODLE_FASHION = ...

    override fun walk() {
        ...
    }
}

В этом примере на самом деле нет никакой причины, что POODLE_FASHION должен быть статическим или постоянным.Это может быть просто val, и это не будет стоить вам ничего лишнего.

При этом, похоже, у вас должен быть класс Poodle, а не объект.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...