Solucionado (ver solução)
Solucionado
(ver solução)
1
resposta

Alterar atributos da Classe mesmo ela sendo val

Bom dia a todos

Eu tava fazendo uns experimentos com a classe e me veio uma dúvida

Quando queremos um atributo com valor imutável, usamos val, e quando não queremos que o mesmo seja imutável, usamos o var.

Mas em relação as classes? pois eu fiz uma classe com val e pude alterar os atributos sem dar problema:

package br.com.alura.classe

fun main() {
    var alex = Conta("Alex",1234,55.60)
    println(alex.getNomeTitular())
    println(alex.getSaldoDaConta())
    alex.depositaDinheiro(50.0)
    alex.setNomeTitular("Alex da Silva")
    println(alex.getSaldoDaConta())
    println(alex.getNomeTitular())
}

No console aparecia assim:

Alex
55.6
105.6
Alex da Silva

e quando eu colocava essa classe como var, aparecia essa mensagem no IntelliJ:

Variable is never modified, so it can be declared using 'val' 

Então, o que tem que ser feito para uma classe ser considerada que foi alterada?

Código da classe completa como referência:

package br.com.alura.classe

class Conta {
    private var nomeTitular:String = "";
    private var numeroDaConta: Int = 0;
    private var saldoDaConta: Double = 0.0;

    constructor(nomeTitular: String, numeroDaConta: Int, saldoDaConta: Double) {
        this.nomeTitular = nomeTitular
        this.numeroDaConta = numeroDaConta
        if (saldoDaConta <0){
            throw Exception("saldo nao pode ser abaixo de 0")
        }
        this.saldoDaConta = saldoDaConta
    }
    fun getNomeTitular():String {
        return nomeTitular
    }
    fun setNomeTitular(nome:String){
        this.nomeTitular = nome
    }
    fun getNumeroDaConta(): Int{
        return numeroDaConta
    }
    fun getSaldoDaConta():Double{
        return saldoDaConta
    }
    fun depositaDinheiro(deposita:Double){
        saldoDaConta += deposita
    }
    fun sacaDinheiro(saca:Double){
        if (saca > saldoDaConta){
            throw Exception("Nao pode sacar mais que seu saldo, que é de $saldoDaConta")
        }
        saldoDaConta -= saca
    }

    override fun toString(): String {
        return "Conta(nomeTitular='$nomeTitular', numeroDaConta=$numeroDaConta, saldoDaConta=$saldoDaConta)"
    }
}

Ps: eu fiz uns cursos de java na Alura antes de fazer esse, por isso eu sei um pouco de programacao

1 resposta
solução!

Fala Murilo, tudo bem?

Pelo que entendi, sua dúvida é porque conseguimos mudar os atributos de um objeto declarado como val, né?

Quando declaramos uma variável de referência a uma classe, estamos guardando de fato a referência para a variável, então internamente ao invés do valor guardado por essa variável ser um objeto, na realidade é um ponteiro, ou referência para onde esse objeto está guardado na memória, assim como acontece no Java. Sendo assim, quando declaramos uma Conta com o val:

var alex = Conta("Alex",1234,55.60)

Internamente a JVM guarda dentro da variável Conta aquele código que representa o espaço da memória, algo como Conta@A42dbe, que aparece quando tentamos imprimir um objeto que não tem o método toString(). Então, conseguimos acessar o objeto e utilizar seus métodos, bem como alterar os seus atributos e ainda assim não estaremos modificando o valor da variável alex, que vai ser sempre Conta@A42dbe.

No entanto, ao tentarmos atrelar essa variável à referência de outra conta, teremos um erro, pois a variável é, sim, imutável.

Portanto, as variáveis de objetos guardam referências e ainda que sejam declaradas como val o objeto pode ser modificado, porém o objeto para o qual a variável aponta, não.

Isso acontece em Java também, é um teste bem interessante: declarar uma variável que aponta para um objeto como final e tentar modificar o objeto, e depois a referência, o comportamento é o mesmo!

Em caso de dúvidas, estou à disposição.

Um grande abraço e bons estudos!

Caso este post tenha lhe ajudado, por favor, marcar como solucionado ✓. Bons Estudos!