:: property.isInitialized не может различить метод и свойство с одинаковым именем - PullRequest
0 голосов
/ 24 августа 2018

Я создаю конструктор (для Java-компата), где context является как частной собственностью, так и открытым методом.

private lateinit var context: Context

fun context(appContext: Context) = apply {
    context = appContext
}

fun build(): MySdk {
    // this::context fails to compile because it cannot differentiate between the 
    // method `context()` vs property `context`
    require(this::context.isInitialized) {
        "context == null"
    }

Но я получаю проблему компиляции для ::context.isInitialized, потому что она не может отличить метод context() от свойства context

Есть ли у Котлина обходной путь для этого? или я вынужден использовать уникальные имена свойств / методов?

Ответы [ 2 ]

0 голосов
/ 24 августа 2018

Вы можете устранить неоднозначность между свойством и методом, указав ожидаемый тип:

val prop: kotlin.reflect.KProperty0<*> = this::context

Увы, prop.isInitialized затем выдает ошибку компиляции:

This declaration can only be called on a property literal (e.g. 'Foo::bar')

Так что в настоящее время это невозможно. OTOH, поскольку ошибка показывает, что isInitialized уже обработан специально компилятором, это, вероятно, можно исправить; Я предлагаю сообщить об этом http://youtrack.jetbrains.com/ (после поиска дубликатов).

0 голосов
/ 24 августа 2018

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

Это из-за вызываемых ссылок (: :).Внутренне, когда вы используете вызываемые ссылки, он вызывает метод.

Вызываемые ссылки : Ссылки на функции, свойства и конструкторы, помимо внутреннего анализа структуры программы, также могут вызываться или использоваться как экземпляры типов функций.

Общий супертип для всех вызываемых ссылок: KCallable , где R - это тип возвращаемого значения, который является типом свойства для свойств, и созданный тип для конструкторов.

KCallable<out R> // supertype for all callable references

Итак, для функции типом является KFunction , а для свойств типом является KProperty

interface KFunction<out R> : KCallable<R>, Function<R> (source)
interface KProperty<out R> : KCallable<R> (source)

Когда вы используете такую ​​функцию, как:

fun context(appContext: Context) = apply {
    context = appContext
}

Может использоваться как ссылка на функцию

::context // This is a Function reference i.e. KFunction

При использовании ссылки на свойство, например

private lateinit var context: Context
fun something(){
    ::context // this is a property reference, KProperty   
}

Ссылка на свойство может использоваться, когда функция с одниможидаемый параметр:

 val strs = listOf("a", "bc", "def")
 println(strs.map(String::length))

Таким образом, Kotlin не заставляет вас использовать разные имена свойств и функций («хотя это не рекомендуется»).Просто в этом случае его невозможно различить как

  1. Оба являются KCallable и имеют одинаковые имена
  2. Ссылка на свойство может использоваться, когда ожидается функция с одним параметром
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...