Incorrecto "esto" se usa en cierres nesteds

Intento mantener esto mínimo, pero avíseme si soy demasiado mínimo.

Supongamos que tiene una jerarquía de classs como esta, diseñada para generar HTML (inspirada en el tutorial de Kotlin, seguido de semi-pseudocódigo):

class Tag { protected val children = arrayListOf<Tag>() operator fun String.unaryPlus() = children.add(Text(this)) } class TagWithChildren : Tag() { fun head(init: Head.() -> Unit) = initializeTag(Head(), init) fun script(init: Script.() -> Unit) = initializeTag(Script(), init) fun <T : Tag> initializeTag(tag: T, init: T.() -> Unit): T { tag.init() children.add(tag) return tag } } class Head : TagWithChildren() class Script : Tag() class Text(val str: Text) : Tag() 

Observe que Head tiene methods de head y script , mientras que Script no.

Ahora puedes build una plantilla que se vea así:

 head { script { +"alert('hi');" } } 

¡Lo cual funciona genial! Sin embargo, si el bloque pasado a la script de script intenta llamar a methods que no están disponibles en la Script de Script , puede llamar al método en la cabeza en su lugar . Por ejemplo,

 head { script { script { +"alert('hi');" } } } 

no solo no es un error de compilation, en realidad es equivalente a

 head { script { } script { +"alert('hi');" } } 

que es muy confuso , desde la perspectiva de un autor de plantilla.

¿Hay alguna manera de evitar que las búsquedas de methods viajen por el ámbito de esa manera? Solo quiero que mire el scope más interno.


ACTUALIZACIÓN 24/11/2016: Kotlin 1.1-M03 ha introducido el control de scope, que creo que resuelve exactamente este problema. https://blog.jetbrains.com/kotlin/2016/11/kotlin-1-1-m03-is-here/

El comportamiento actual es intencional. El código en una lambda tiene acceso a los receptores de todos los ámbitos adjuntos. Es posible que una versión futura de Kotlin agregue un modificador que restringirá una lambda con receptor a los methods de llamada en ese receptor solamente y no en los ámbitos circundantes, pero en la versión actual no hay manera de cambiar ese comportamiento.

Como solución alternativa, puedo hacer que falle en el time de ejecución si cambio las classs para que se vean así:

 open class Tag { operator fun String.unaryPlus() // pulled up from TagWithChildren, call protected method fun head(init: Head.() -> Unit) = addChild(Head()) fun script(init: Script.() -> Unit) = addChild(Head()) // throws in Tag open protected fun addChild(t: Tag) = throw IllegalArgumentException() } class TagWithChildren : Tag() { // overridden to not throw in subclass protected override fun addChild(t: Tag) = children.add(t) } 

De esta forma, cada Tag tiene los methods de compilation (que resuelven el problema del scope), pero en realidad llamarlos puede provocar un error en el time de ejecución.

  • Cómo get datos de más de una aplicación json
  • cómo a la matriz de initialization en Kotlin?
  • NoSuchMethodError: java.lang.Long.hashCode
  • ¿Cómo puedo get valor de observable
  • KClass de reference sin resolver tratando de usar DBFlow y Kotlin con Android
  • Variable opcional de class de datos de Kotlin
  • Interfaces de Kotlin exportando a properties perdidas de Javascript
  • Herencia de classs de datos de Kotlin + método de copy
  • ViewModel for Fragment en su lugar accediendo a Activity ViewModel?
  • Datos de spring mongodb y kotlin
  • Deserialization Kotlin Firebase