¿Podemos lograr security de tipo de time de compilation para una unión de types que no podemos controlar?

Digamos que tengo una function:

fun doSomething(vararg pairs: Pair<String, *>) { // Do things with the pairs } 

El problema con este enfoque es que permite cualquier tipo para la segunda mitad de Pair (por ejemplo, Pair<String, CustomType1> ).

¿Qué pasa si solo quiero permitir un número finito de types, cómo lo lograría?

Si la function tuviera una firma más simple, podría lograr la restricción por sobrecarga, así:

 fun doSomethingSimpler(param: Boolean) { // Boolean implementation } fun doSomethingSimpler(param: Int) { // Int implementation } // etc. 

Si el tipo restringido "establecer" estuviera bajo mi control, podría usar una interfaz o una class sellada para lograr esto. P.ej

 sealed class Root class Child1 : Root() class Child2 : Root() fun doSomethingICanControl(param: Root) { // Root implementation } 

Sin embargo, ¿qué ocurre si no tengo control sobre los types o si son primitivos? ¿Cómo evito * permita todo?

Sé que podría usar Smart-Cast para get security en time de ejecución, pero ¿se puede hacer esto en time de compilation?

¿O el lenguaje no lo permite?

Editar 1

Sé que podría crear mis propios types de cajas (p MyBoolean Ej., MyBoolean ) y usar una interfaz común o una class sellada, pero eso sería una repetición que todos deberían escribir cada vez que lo necesitaran.

Editar 2

Para ser claro, me gustaría poder hacer una invocación así:

 doSomething( "key1" to false, "key2" to "value2", "key3" to 86 ) 

… Es decir, tienen un set mixto de types "segundo" (de Pair ).

Entonces, resumirlo rápidamente:

Desea llamar a methods desde una biblioteca que espera Pair<String, *> , pero limita los posibles valores * .

TL; DR: Lo que intentas lograr no es posible sin algún tipo de envoltorio, porque

  1. No tenemos Sum-Types en Kotlin, así que no hay forma de decirle al comstackdor que esperas un Int o un Double o un Float y nada más
  2. Si un método de biblioteca espera que algo sea Pair<String, *> , no hay forma de que le digamos al comstackdor que solo queremos darle un String lugar de *

Una forma de get ese comportamiento es crear un Decorador ( Patrón Decorador ), por ejemplo, crear sus propios methods de extensión que permitan solo un subset

 class Foo { //Allows everything fun doSomething(param: Pair<String, *>) } //Now lets create our own extension methods fun Foo.doSomethingWithInt(param: Pair<String, Int>) fun Foo.doSomethingWithBoolean(param: Pair<String, Boolean>) fun Foo.doSomethingWithString(param: Pair<String, String>) 

O si no desea poder llamar a Foo.doSomething() , puede crear una Decoractor-Class:

 class FooDecorator { val foo = Foo() fun doSomething(param: Pair<String, Int>) { } } 

Y el siguiente ejemplo no es posible sin algún tipo de Wrapper, porque no hay Sum-Types en Kotlin:

 doSomething( "key1" to false, "key2" to "value2", "key3" to 86 ) 

Lo que podrías hacer es algo así como:

Al principio, crea tu propio tipo JSONItem y agrega Extension-Methods a Types que se pueden usar como uno

 class JSONItem<T> private constructor (item: T) fun Int.asJSONItem() = JSONItem(this) fun String.asJSONItem() = JSONItem(this) fun Boolean.asJSONItem() = JSONItem(this) 

Entonces puedes hacer algo como eso:

 //Your own personal doSomething fun doSomething(varargs: param: Pair<String, JSONItem>) { //Call the real doSomething() doSomething(param.map { Pair(it.first, it.second.item) }} } doSomething( "key1" to false.asJSONItem(), "key2" to "value2".asJSONItem(), "key3" to 86.asJSONItem() ) 

Los types de combinación e intersección denotable actualmente no son compatibles con Kotlin (a partir de 1.1.x).

Este es el problema relevante.

  • Obteniendo un NoClassDefFoundError al llamar a una function de extensión kotlin
  • Usando Kotlin con Dagger
  • ¿Cómo puedo identificar cuándo se mapeará un tipo de Kotlin a un tipo de Java?
  • ¿Cómo encontrar el directory de documentos del usuario con Kotlin?
  • Herencia de la interfaz: extiende una interfaz en Kotlin
  • ¿Cómo obtengo una KProperty1 de una KProperty0?
  • ¿Cómo get los nombres de los parameters a través de la reflexión en kotlin?
  • ¿Cómo se configura una construcción multiplataforma de Kotlin?
  • Gradle KTS. ¿Cómo mover la configuration de dependencies a un file separado de la compilation principal?
  • Controlador de enlace con clic en TextView
  • Kotlin: Bloqueando corutinas con E / S sin locking