Случайное переопределение: следующие объявления имеют одинаковую подпись JVM

Я получаю ошибку в Котлине в этой части:

class GitHubRepoAdapter(
    private val context: Context,
    private val values: List<GithubRepo>
) : ArrayAdapter<GithubRepo>(
    context, 
    R.layout.list_item,
    values
)

private val context: Context

В журнале написано:

Error:(14, 25) Accidental override: The following declarations have the same JVM signature
(getContext()Landroid/content/Context;):  
    fun <get-context>(): Context  
    fun getContext(): Context!

Я не могу понять, в чем проблема.


person Ege Kuzubasioglu    schedule 17.05.2017    source источник
comment
Может быть, это будет полезно stackoverflow.com/questions/29268526/   -  person Lu55    schedule 08.02.2019


Ответы (3)


Это происходит потому, что компилятор Kotlin пытается сгенерировать геттер для val context, объявленного в основном конструкторе вашего класса, а именно метод getContext(), но базовый класс _ 3_ уже есть такой метод.

Вы можете решить эту проблему, выполнив одно из следующих действий:

  • Измените параметр конструктора вашего класса так, чтобы он не был val.

       class GitHubRepoAdapter(context: Context, ...
    

    В этом случае геттер не будет сгенерирован и конфликт исчезнет.

    Это кажется предпочтительным решением в вашем случае, потому что даже без повторного объявления там уже является синтетическим свойством context, полученным из получателя Java.

  • Используйте аннотацию @JvmName, примените его к геттеру свойства context:

       class GitHubRepoAdapter(@get:JvmName("getAdapterContext") private val context: Context, ...
    

    Это заставит компилятор сгенерировать геттер с другим именем JVM (указанным в аннотации), что позволит избежать конфликта, но сделает доступ к нему из Java менее интуитивно понятным (тем более, что будут две похожие функции). В Kotlin вы по-прежнему сможете использовать свойство с исходным именем context.

person hotkey    schedule 17.05.2017
comment
Это работает со свойствами val, унаследованными от интерфейса? Я имею ввиду например интерфейс с val context: Context? - person Karol Kulbaka; 18.12.2018

В дополнение к уже данному ответу ...

  • Или вы можете оставить val (или var), но изменить имя параметра на такое, которое не противоречит объявлению суперкласса.

В объявлении класса параметры в объявлениях конструктора часто являются чем-то большим, чем просто параметрами. Используя val или var, вы фактически объявляете элементы свойств (а не только параметры). А вместе с членами свойств идут автоматические «геттеры» (и «сеттеры» в случае var). Автоматический получатель в случае OP называется getContext() , но базовый класс уже имеет getContext () (такая же подпись).

Скорее всего, здесь было намерение просто передать context суперу, и в этом случае лучше всего подходит другой ответ. Но в случае, когда требуется новое свойство, но выбранное имя сталкивается с другим назначенным членом суперпользователя, изменение имени является альтернативой.

Короче говоря, изменение имени применяется, когда вам действительно нужна новая переменная-член, но суперкласс уже предоставляет другой член с тем же именем.

person Les    schedule 27.07.2017
comment
Я думаю, что эта версия предпочтительнее принятого ответа. Если у моего суперкласса уже есть свойство / получатель / сеттер для переменной, зачем мне вообще создавать второй? Удаление val/var наверняка кажется самым удачным способом. - person withoutclass; 28.07.2017
comment
@withoutclass - вы неправильно поняли мой ответ, мой на самом деле говорит, что вы можете оставить val или var и просто изменить имя переменной, что полезно, когда суперкласс уже использует выбранное вами имя. В случае, когда суперкласс использует имя для свойства с совершенно другой целью, чем то, что вы планировали для своей переменной, тогда уместно новое свойство с другим именем. Я обновлю свой ответ, чтобы он был более понятным. - person Les; 28.07.2017

Измените имя переменной на myContext, и все будет работать с вами без проблем.

person Hamdy Abd El Fattah    schedule 28.08.2020