почему один получает "Столкновение декларации платформы", а другой в порядке? - PullRequest
0 голосов
/ 08 октября 2018

Определив интерфейс:

interface IData {

    fun getHash() : Int
    fun getUUID(): UUID

    ......
}

Попытка создать объект для интерфейса.fun getUUID(): UUID в порядке, но fun getHash() : Int получил ошибку, как показано ниже.

Что может быть не так?почему они разные?

fun buidlDataList () : ArrayList<IData> {

    val dataList = ArrayList<IData>(0)

    dataList.add(object : IData {

        val hash: Int by lazy { dataFetchers.size+System.currentTimeMillis().toInt() } //<=== get error
        override fun getHash(): Int {                                                  //<=== get the same error
            return hash
        }

        val uuid: UUID by lazy { UUID.randomUUID() }
        override fun getUUID(): UUID {
            return uuid
        }
        ......
    }
}


Platform declaration clash:  The following declarations have the same JVM signature(getHash() I):
    * public final fun <get-hash>(): int  defined in com.data. buidlDataList <no name provided>
    * public open fun getHash(): int defined in defined in com.data. buidlDataList <no name provided>

1 Ответ

0 голосов
/ 08 октября 2018

Переменные создают свои собственные методы получения, но вы также явно определяете их.Когда вы объявляете var или val, они обычно имеют свои собственные геттеры, автоматически генерируемые 1 .Частные значения или переменные не нужны, если вы не создаете пользовательский метод получения.

Но во всех остальных случаях это:

val x: Int = TODO()

генерирует геттер 1 .

В вашем случае я бы рекомендовал использовать val непосредственно в интерфейсе.Видите ли, сгенерированный метод get имеет то же имя, что и метод getHash, который вы явно объявили.Получатели также не переопределяют методы (если только вы не аннотируете это одной из аннотаций @Jvm, и я не помню, какие из них, но вы все равно не нужны).

Таким образом, вы изменяете свой интерфейс на:

interface IData {
    val hash: Int
    val uuid: UUID
}

И удаляете геттеры в переопределенном объекте и добавляете override к значениям:

dataList.add(object : IData {
    override val hash: Int by lazy { dataFetchers.size+System.currentTimeMillis().toInt() }
    override val uuid: UUID by lazy { UUID.randomUUID() }
}

Первый интерфейс фактически эквивалентен объявлению интерфейса с методами get и set.Если вы переопределите его из Java, он попросит вас переопределить getHash() и getUid(), и вам нужно будет объявить поле локально.Kotlin работает по-другому, потому что он автоматически генерирует сеттеры.

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


Кроме того, если вы декомпилируете байт-код Kotlin, вы увидите, для чего компилируется интерфейс с переменными:

public interface IData {
   int getHash();

   @NotNull
   UUID getUuid();
}

Таким образом, он идентичен тому, который был у вас изначально,просто без конфликтов в дочерних классах из-за конфликтов имен переменных.


И причина того, что только у одного есть конфликт, заключается в том, что, как вы видите в интерфейсе, val uuid создает геттер с именем getUuid, а ваш интерфейс объявляет getUUID.Методы в Java и Kotlin чувствительны к регистру, поэтому они не конфликтуют.Если вы переименуете свою переменную в верхний регистр UUID, вы также столкнетесь с этим.

1: Предполагается, что переменная / константа отсутствует в методе.Переменные верхнего уровня, переменные в интерфейсах, перечисления, классы, объекты и сопутствующие объекты - все генерируют геттеры / сеттеры, но если вы объявите переменную внутри метода, у нее, естественно, не будет геттеров и сеттеров, где это применимо.

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