Ссылка на функцию для конструктора класса, вложенного в родительский класс generi c - PullRequest
1 голос
/ 04 марта 2020

Если у меня есть

sealed class Foo<A> {
  data class Bar<A>(val value: Int): Foo<A>()
}

и я хочу сослаться на конструктор Bar<Int> как на неявную лямбду, используя оператор ::, то ни один из следующих вариантов не будет принят в качестве допустимого синтаксиса:

  • Foo<Int>::Bar<Int>
  • ::Foo.Bar<Int>
  • ::(Foo.Bar<Int>) (компилятор сообщает, что этот синтаксис зарезервирован для будущего использования).

I может ссылаться на него, если я явно импортирую вложенный конструктор класса в область видимости, используя

import com.package.Foo.Bar

, что позволяет мне написать ::Bar для конструктора и Bar<Int>::value для Собственник добытчик. Но я должен сделать это для каждого вложенного конструктора, и это отчасти сводит на нет преимущество использования оператора :: для сохранения ввода.

Есть ли пропущенная запись, которая позволяет мне избежать необходимости импортировать все вложенные имена классов и конструкторы?

Edit

В моем исходном примере не использовались дженерики, что, как оказалось, было упрощением проблемы, с которой я столкнулся в моем реальном коде, над которым я работаю, который использует использует дженерики.

Оказывается, что для вложенных классов без параметров generi c нотация Foo::Bar действительно работает, поэтому мой исходный вопрос имел неверную предпосылку. Однако невозможно создать вызываемые ссылки на конструкторы внутри обобщенных c классов. Это задокументировано в следующем отчете об ошибке: https://youtrack.jetbrains.com/issue/KT-15952

Ответы [ 3 ]

1 голос
/ 04 марта 2020

А как насчет импорта подстановочных знаков?

import com.package.Foo.*
1 голос
/ 04 марта 2020

Это известная ошибка в дизайне языка: https://youtrack.jetbrains.com/issue/KT-15952

Однако этот отчет об ошибке привел меня к другому обходному пути с использованием псевдонимов типов, который эквивалентен добавлению псевдонимов импорта, но имеет то преимущество, что вы можете поместить псевдоним там, где вы хотите, и даже разделить его между модулями. Таким образом, это два единственных жизнеспособных решения, о которых я знаю:

// Method one: Import Foo.Bar

import Foo.Bar as BarImported

sealed class Foo<A> {
  data class Bar<A>(val value: A): Foo<A>()
}

val ctor: (Int) -> Foo<Int> = ::BarImported
val getter: (BarImported<Int>) -> Int = BarImported<Int>::value


// Method two: Alias Foo.Bar
typealias BarAlias<A> = Foo.Bar<A>

val ctor2: (Int) -> Foo<Int> = ::BarAlias
val getter2: (Foo.Bar<Int>) -> Int = BarAlias<Int>::value
0 голосов
/ 04 марта 2020

Я почти уверен, что Kotlin относится к Foo и Foo.Bar как к совершенно не связанным классам, поэтому импорт Foo не даст вам доступа к Bar автоматически. Вы на самом деле должны импортировать его отдельно; Я не могу найти подробности на kotlinlang.org , хотя ...

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