class Person(val name:String,var age:Int )
def person = new Person("Kumar",12)
person.age = 20
println(person.age)
Estas líneas de código de salida 12
, a pesar de que person.age=20
se ejecutó con éxito. Descubrí que esto sucede porque usé def en def person = new Person("Kumar",12)
. Si uso var o val, la salida es 20
. Entiendo que el valor predeterminado es val in scala. Esta:
def age = 30
age = 45
... da un error de compilación porque es un valor por defecto. ¿Por qué el primer conjunto de líneas anteriores no funciona correctamente y, sin embargo, tampoco produce errores?
val
se puede cambiar pero el objeto al que se refiere un val no. Aval
no es una constante.List
comofinal
, pero podría modificar su contenido.Comenzaría por la distinción que existe en Scala entre def , val y var .
def : define una etiqueta inmutable para el contenido del lado derecho que se evalúa perezosamente : evalúe por nombre.
val - define una etiqueta inmutable para el contenido del lado derecho que se evalúa con entusiasmo / de inmediato - evaluado por valor.
var : define una variable mutable , inicialmente establecida en el contenido evaluado del lado derecho.
Ejemplo, def
Ejemplo, val
Ejemplo var
Según lo anterior, las etiquetas de def y val no se pueden reasignar, y en caso de cualquier intento, se generará un error como el siguiente:
Cuando la clase se define como:
y luego instanciado con:
se crea una etiqueta inmutable para esa instancia específica de Persona (es decir, 'personaA'). Cada vez que el campo mutable 'edad' necesita ser modificado, tal intento falla:
como se esperaba, 'age' es parte de una etiqueta no mutable. La forma correcta de trabajar en esto consiste en usar una variable mutable, como en el siguiente ejemplo:
como claro, a partir de la referencia de variable mutable (es decir, 'persona B') es posible modificar el campo mutable de clase 'edad'.
Todavía enfatizaría el hecho de que todo proviene de la diferencia mencionada anteriormente, eso tiene que estar claro para cualquier programador de Scala.
fuente
personA
et al. parece apagado Si la modificación delage
miembro funciona o no es independiente de si usadef personA
o novar personB
. La diferencia es que en eldef personA
caso de que esté modificando laPerson
instancia devuelta de su primera evaluación depersonA
. Esta instancia se modifica, pero no es lo que se devuelve cuando una vez más evalúapersonA
. En cambio, la segunda vez que lo haces,personA.age
lo estás haciendo de manera efectivanew Person("Tim",25).age
.Con
está definiendo una función / variable perezosa que siempre devuelve una nueva instancia de Person con el nombre "Kumar" y edad 12. Esto es totalmente válido y el compilador no tiene motivos para quejarse. Llamar a person.age devolverá la edad de esta instancia de Person recién creada, que siempre es 12.
Cuando se escribe
asigna un nuevo valor a la propiedad age en la clase Person, que es válido ya que age se declara como
var
. El compilador se quejará si intenta reasignarloperson
con un nuevo objeto Person comofuente
Para proporcionar otra perspectiva, "def" en Scala significa algo que se evaluará cada vez que se use, mientras que val es algo que se evalúa de inmediato y solo una vez . Aquí, la expresión
def person = new Person("Kumar",12)
implica que siempre que usemos "persona" recibiremos unanew Person("Kumar",12)
llamada. Por lo tanto, es natural que los dos "person.age" no estén relacionados.Así entiendo Scala (probablemente de una manera más "funcional"). No estoy seguro si
Sin embargo, es realmente lo que Scala pretende decir. Realmente no me gusta pensar de esa manera al menos ...
fuente
Como ya dice Kintaro, la persona es un método (debido a def) y siempre devuelve una nueva instancia de Person. Como descubrió, funcionaría si cambia el método a var o val:
Otra posibilidad sería:
Sin embargo,
person.age=20
en su código está permitido, ya que obtiene unaPerson
instancia delperson
método, y en esta instancia puede cambiar el valor de avar
. El problema es que después de esa línea no tiene más referencia a esa instancia (ya que cada llamada aperson
producirá una nueva instancia).Esto no es nada especial, tendría exactamente el mismo comportamiento en Java:
fuente
Tomemos esto:
y reescribirlo con un código equivalente
Ver,
def
es un método. Se ejecutará cada vez que se llame y cada vez que regrese (a)new Person("Kumar", 12)
. Y esto no es un error en la "asignación" porque no es realmente una asignación, sino solo una llamada alage_=
método (proporcionado porvar
).fuente