Intereting Posts
Нестандартное представление Android для медленного рендеринга с возможностью выделения фона Карта Mybatis COALESCE (int, 0) на java.lang.Long LiveData Observver поймает только первое значение Android Kotlin Realm Правильный способ запроса + вернуть неуправляемые элементы в Bg Thread Как поместить несколько ящиков рядом друг с другом в вертикально прокручиваемом виде в Android Studio? Ошибка компилятора Java при связывании с бандой компилятора kotlin с использованием ant RxKotlin: попытка добавления пользовательских ошибок в ловушку раньше в Котлине Как я могу вызвать методы Kotlin с помощью reified generics из Java? Запуск приложения TornadoFX из существующей программы Kotlin Escape $ {something} в строчке Котлина создание приемлемого объекта в котлине Val не может переназначить ошибку времени компиляции для локальной переменной в fun в kotlin kotlin получает подписчика для наблюдения наблюдаемого с помощью RxJava2 Почему у Kotlin есть два синтаксиса для lambdas / анонимных функций?

Попросите класс Non-Generic использовать общий аргумент в конструкторе

Я хотел бы иметь не-общий класс в kotlin, который использует generics в своем конструкторе, чтобы указать этот параметр. Однако я не могу понять, как это сделать, и конвертер Java-to-Kotlin для Intellij прерывается.

Мой класс java выглядит так

public class Test { interface I1 { } interface I2 { } private final I1 mI1; private final I2 mI2; public <T extends I1 & I2> Test(T host) { mI1 = host; mI2 = host; } } 

Выход преобразователя выглядит так.

 class Test(host: T) where T: I1, T: I2 { internal interface I1 internal interface I2 private val mI1: I1 private val mI2: I2 init { mI1 = host mI2 = host } } 

Я хотел бы сделать это, потому что в разработке Android полезно указать параметр конструктора, который выглядит так: <Host extends Context & CustomCallbackInterface>

Глядя на грамматику Котлина, кажется, что на данный момент это невозможно. Для первичных конструкторов параметры типа обозначают параметры типа класса:

 class (used by memberDeclaration, declaration, toplevelObject) : modifiers ("class" | "interface") SimpleName typeParameters? primaryConstructor? (":" annotations delegationSpecifier{","})? typeConstraints (classBody? | enumClassBody) ; 

Для вторичных конструкторов нет параметров типа:

 secondaryConstructor (used by memberDeclaration) : modifiers "constructor" valueParameters (":" constructorDelegationCall)? block ; 

Однако конструктор – это просто специальная функция. Если мы вместо этого не будем использовать конструктор, а будем использовать нашу собственную функцию, мы можем придумать следующее:

 class Test { interface I1 interface I2 private val mI1: I1 private val mI2: I2 internal constructor(host: I1, host2: I2) { mI1 = host mI2 = host2 } companion object { fun <T> create(host: T): Test where T : Test.I1, T : Test.I2 { return Test(host, host) } } } fun <T> test(host: T): Test where T : Test.I1, T : Test.I2 { return Test(host, host) } 

Теперь мы можем вызвать Test.create(host) или test(host) для создания экземпляра.

Развернувшись на ответе nhaarman , вы можете использовать перегрузку оператора, чтобы обеспечить совместимость объекта Test с operator invoke :

 class Test { interface I1 interface I2 private val mI1: I1 private val mI2: I2 private constructor(i1: I1, i2: I2) { mI1 = i1 mI2 = i2 } companion object { operator fun <T> invoke(host: T): Test where T : I1, T : I2 { return Test(host, host) } } } 

Затем вы можете создать объект Test с помощью синтаксиса вызова, который вы хотите:

 Test(object : Test.I1, Test.I2 {})