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