Solucionado (ver solução)
Solucionado
(ver solução)
2
respostas

Sobreescrita de métodos

No exemplo a seguir as classes ContaCorrente e ContaPoupanca tem taxas de saque diferentes. Por essa razão os métodos saca() são sobrescritos em cada uma das classes. Quando executo o método saca() a taxa de saque é cobrada normalmente. Porém quando executo o método transfere() que utiliza o método saca() a taxa de saque é desconsiderada. Como resolver esta situação ?

Utilizo a classe Movimentacoes em composicao com as classes Conta. O que eu notei no debug é que quando tento fazer uma transferência, o método transfere() chama o método saca da própria classe Movimentações e não da respectiva Classe conta, onde é tratada a taxa de saque.

public class ContaCorrente implements Conta, Tributavel{

    private Movimentacoes movimentacoes;
    public ContaCorrente (int agencia, int  numero) {
        movimentacoes = new Movimentacoes (agencia, numero);
    }


    @Override
    public void saca(double valor) {

        double valorASacar = valor + 0.2;

            movimentacoes.saca(valorASacar);

    }

    @Override
    public void deposita(double valor) {
        movimentacoes.deposita(valor);

    }

    @Override
    public double getValorImposto() {
        return movimentacoes.getSaldo() * 0.1;
    }

    @Override
    public double getSaldo() {

        return movimentacoes.getSaldo();
    }


    @Override
    public void transfere(double valor, Conta destino) {
        movimentacoes.transfere(valor, destino);

    }



    /*@Override
    public void setSaldo(double valor) {

        movimentacoes.setSaldo(valor);

    }*/

}

public class ContaPoupanca implements Conta, Tributavel{

    private Movimentacoes movimentacoes;
    public ContaPoupanca (int agencia, int  numero) {
        movimentacoes = new Movimentacoes (agencia, numero);
    }


    @Override
    public void saca(double valor) {

        double valorASacar = valor + 0.5;

        movimentacoes.saca(valorASacar);

    }

    @Override
    public void deposita(double valor) {
        movimentacoes.deposita(valor);

    }

    @Override
    public double getValorImposto() {
        return movimentacoes.getSaldo() * 0.1;
    }

    @Override
    public double getSaldo() {

        return movimentacoes.getSaldo();
    }


    @Override
    public void transfere(double valor, Conta destino) {
        movimentacoes.transfere(valor, destino);

    }



    /*@Override
    public void setSaldo(double valor) {

        movimentacoes.setSaldo(valor);

    }*/
}


public class Movimentacoes {


    private int agencia;
    private int numero;
    private double saldo;
    private Cliente titular;


    public Movimentacoes(int agencia, int numero) {


        this.agencia = agencia;
        this.numero = numero;
        this.saldo = 0;
        System.out.println("Estou criando uma conta " + this.numero);
    }    


    public void saca(double valor) {

        if (this.saldo < valor) {
            throw new SaldoInsuficienteException("Saldo: " + this.saldo +", Valor: " + valor);
        }    
            this.saldo -= valor;    
    } 


    public void deposita(double valor) {
        this.saldo += valor;
    }

    public void transfere(double valor, Conta destino) {
        this.saca(valor);
        destino.deposita(valor);

    }

    /*public void setSaldo(double saldo) {
        this.saldo = saldo;
    }*/

    public double getSaldo() {
        return saldo;
    }

    public void setTitular(Cliente titular) {
        this.titular = titular;
    }

    public Cliente getTitular() {
        return titular;
    }


}

2 respostas

Olá Maurício, tudo bem com você?

O jeito é não usar o método transfere() de Movimentacoes, já que ele não aplica nenhuma taxa no saque. Como eu não sei como está a sua interface Conta, acredito que a única solução que eu possa te passar é simplesmente deixar a Conta como classe abstrata e usá-la no lugar de Movimentacoes para que suas subclasses chamem o construtor dela e possam ter acesso à agencia e ao numero, eliminando a necessidade de fazer composição.

A questão é que nesse caso, usar interface e composição pode não fazer muito sentido. Estamos deixando o problema mais complexo para resolver um problema que a herança deve resolver. Perceba que no exemplo da aula onde o Nico usa a classe AutenticacaoUtil para fazer a composição, todas as classes que fazem uso dela tem exatamente o mesmo comportamento nos métodos setSenha() e autentica(). Diferente desse caso, onde devemos ter um comportamento diferente (uma taxa diferente) para cada método saca(). Então, apresento uma outra solução, nos métodos transfere() das suas contas, retira a chamada movimentacoes.transfere(valor, destino) e chama os métodos saca() e deposita() no lugar. Os outros métodos podem continuar como estão, mudamos apenas esse método que exige comportamentos diferentes.

@Override
public void transfere(double valor, Conta destino) {
    this.saca(valor);
    destino.deposita(valor);
}

Existem outras soluções para esse problema, mas eu acredito que nesse caso não tem como fugir muito da repetição de código sem usar herança. Mesmo o James Gosling dizendo que queria ter feito o Java usando apenas interfaces e composição, infelizmente nem ele conseguiu escapar da herança nesses casos como ele mesmo mencionou em uma de suas intrevistas! rs

Como já faz quatro dias que você abriu o tópico, pode ser que você já tenha resolvido. Mas me diz aí se você conseguiu encontrar uma solução que funcionasse melhor para esse caso! ;)

solução!

Deve ser isso mesmo Thiago. Obrigado. Na verdade a transformação em interface e composição foi mais a título de exercício mesmo já que o nico falou que esta solução era a mais usual atualmente. Mas ficou claro com este problema que em determinadas situações não da pra fugir da superclasse.