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=20se 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?

valse puede cambiar pero el objeto al que se refiere un val no. Avalno es una constante.Listcomofinal, 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
personAet al. parece apagado Si la modificación delagemiembro funciona o no es independiente de si usadef personAo novar personB. La diferencia es que en eldef personAcaso de que esté modificando laPersoninstancia 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.agelo 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 reasignarlopersoncon 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=20en su código está permitido, ya que obtiene unaPersoninstancia delpersonmé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 apersonproducirá 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,
defes 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