new method example create companion inheritance side-effects kotlin

inheritance - method - Error o característica: Kotlin permite cambiar ''val'' a ''var'' en herencia



new en kotlin (2)

Consideraría esto como una característica, ya que cambiar val a var impone restricciones de uso más débiles y no puede romper ningún código de superclase . Situación similar puede observarse con modificadores de visibilidad:

trait A { protected fun print() { ... } } class AImpl: A { public override fun print() { ... } }

En este ejemplo, las restricciones de visibilidad también se relajan en una subclase, aunque algunas personas consideran esta técnica como una antipaterna.

¿Cómo protejo los valores para que no se modifiquen por herencia?

En kotlin puede definir explícitamente si un miembro de una clase en particular puede ser anulado por una subclase usando open modificador open . En rasgos, sin embargo, todos los miembros están abiertos por defecto. La solución es reemplazar el rasgo por clase, para que puedas controlar la herencia:

abstract class A { fun print() { ... } val x : Int = 2; } class AImpl(x : Int) : A() { override var x = x // compilation error }

Acabo de empezar a explorar el lenguaje Kotlin. Estoy luchando con la herencia, var & val y efectos secundarios.

Si declaro un rasgo A con un val x y AImpl x en AImpl , es posible anularlo como var (ver código a continuación). Sorprendentemente, el método print() en A se ve afectado por la reasignación de x , aunque x es un valor en A ¿Es este un error o una característica?

Código:

trait A { fun print() { println("A.x = $x") } val x : Int; } class AImpl(x : Int) : A { override var x = x; // seems like x can be overriden as `var` } fun main(args: Array<String>) { val a = AImpl(2) a.print() // A.x = 2 a.x = 3; // x can be changed // even though print() is defined in trait A // where x is val it prints x = 3 a.print() // A.x = 3 }

Soy consciente del hecho de que si defino a con el tipo A explícitamente, no está permitido cambiar x :

val a = AImpl(2) : A a.x = 3 // ERROR: value x cannot be reassigned

Pero como muestra el primer caso, la herencia puede causar efectos secundarios que claramente no se pretenden en A ¿Cómo protejo los valores para que no se modifiquen por herencia?


Usted puede hacer que su val final , es decir, prohibir anularlo en absoluto. Si define un val en una clase, es final por defecto.

Además, si necesita anular un valor val con un var , pero no quiere que el configurador sea público, puede decirlo:

override var x = 1 private set

Reemplazar una val con una var es una característica . Es equivalente a agregar un método set mientras que en la superclase solo había un método get. Y esto es bastante importante en la implementación de algunos patrones, como las interfaces de solo lectura.

No hay manera de "proteger" a su val de ser anulado de una manera que permita cambiar la mutación de otra manera que hacerlo final , porque val no significa "referencia inmutable", sino simplemente "propiedad de solo lectura". En otras palabras, cuando su rasgo A declara un val , significa que a través de una referencia de tipo A el cliente no puede escribir este val , ninguna otra garantía prevista, o incluso posible.

Los puntos y coma PS son opcionales en Kotlin, siéntase libre de omitirlos por completo