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

Dúvida quanto a classes

Bem, estou estudando e bateu uma dúvida sobre boa prática quanto a classes. Bem, tenho uma classe chamada CONTA e outra classe chamada CLIENTE. Eu quero que minha classe Cliente possa ser apenas instanciada na classe Conta, ou seja, quero que eu não consiga acessar a classe Cliente através da main .

Depois de tanto pesquisar e tentar, a única forma que consegui fazer isso foi fazendo classes aninhadas (não sei se isso é uma boa prática). Segue o código abaixo:

public class Conta {

    public class Cliente {
        private String nome;
        private String endereco;


        public String getNome(){
            return nome;
        }

        public void setNome(String nomeDoClinete){
            nome = nomeDoClinete;
        }

        public String getEndereco(){
            return endereco;
        }

        public void setEndereco(String enderecoDoCliente){
            endereco = enderecoDoCliente;
        }
    }

    public Cliente titular = new Cliente();
    private double[] historico = new double[50];
    private double totalDaConta = 0;
    private int identificador;

    static int contador = 0;

    public double[] getHistorico() {
        return historico;
    }

    public void setHistorico(double[] historico) {
        this.historico = historico;
    }

    public double getTotalDaConta() {
        return totalDaConta;
    }

    public void setTotalDaConta(double totalDaConta) {
        this.totalDaConta = totalDaConta;
    }

    public int getIdentificador() {
        return identificador;
    }

    public void setIdentificador(int identificador) {
        this.identificador = identificador;
    }
}

Código da Classe Principal:


public class Programa {
    public static void main(String[] args) {
        Conta testePessoa = new Conta();

        testePessoa.titular.setNome("Cliente teste");

        //Testando a saída
        System.out.println(testePessoa.titular.getNome());


        //Se eu tentar instanciar um objeto Cliente...
        Cliente testeCliente = new Cliete(); //não consigo
    }
}

Então essa foi a única forma que encontrei para não poder instanciar Cliente dentro da main. Mas achei que o código ficou muito confuso e poluído. Queria saber se esse é o melhor método?

Grato.

11 respostas

Duas classes dentro de um único arquivo .java realmente não é interessante.

Por qual motivo você quer restringir a instanciação da classe Cliente? Você quer que exista um cliente para poder existir uma conta?

Acho que é mais semanticamente correto dizer que um cliente tem uma conta, e não o contrário. De qualquer forma, se você realmente precisa que uma conta só seja acessível pelo cliente, que tal colocar as duas contas dentro de um pacote específico, e utilizar o modificador de acesso default para (no seu caso) Cliente. Assim, somente Conta terá acesso ao cliente.

Deu pra entender?

Entendi. Acho que isso resolveria o problema, mas acho que tenho uma solução melhor.

Que tal separar as classes em arquivos diferentes e criar um único construtor na classe Conta, com um parâmetro do tipo Cliente.

public Conta(Cliente cliente) {
    this.cliente = cliente;
}

Dessa forma, só será possível instanciar uma Conta se tiver um Cliente. Caso você queira implementar mais construtores, lembre-se sempre de exigir um Cliente.

O que acha dessa solução?

Mas assim ainda seria possível ter um cliente sem estar associado a uma conta. Esse é o efeito desejado?

Esse foi o efeito desejado, porque na solução que eu pensei, um cliente pode ter nenhuma ou várias contas.

Mas se o objetivo for cria um relacionamento 1 para 1, onde um cliente deve ter apenas uma conta e uma conta deve ter apenas um cliente, essa solução não é a ideal.

Nesse tipo de relacionamento, pode ser feito o que você sugeriu, colocar as classes em um mesmo pacote, e colocar o construtor de uma delas como protected, assim apenas as classes do mesmo pacote podem instancia-lá.

Outra solução seria unir as duas classes em uma única classe, unindo os atributos, já que o relacionamento é 1 para 1.

Class Conta {
    private String nomeCliente;
    private String enderecoCliente;
    // atributos da conta
    // ...

Protected não. Protected indica que apenas as classes herdeiras terão acesso. O modificador é o default (sem nada escrito).

Conseguiu Luan?

Pessoal, obrigado pela ajuda de todos! Então, consegui mais ou menos. Fiz de uma maneira em que instanciei um objeto Cliente dentro da Classe Conta e deixei o modificador como public. Assim quando eu instancio o objeto Conta tenho acesso aos métodos modificadores da Classe Cliente.

Mas a única forma foi essa. Não sei se dessa forma é uma boa prática, pós queria meus atributos todos privados. Outra, mesmo assim ainda consigo instanciar um Cliente sem ter uma conta.

Sobre pacotes, ainda não cheguei nessa parta no curso. Vou dar uma olhada depois.

Sobre a semântica, acredito que o cliente pertence a conta, não ao contrário. A conta pertence a alguma entidade ou instituição e você só é o titular dela, então seu nome é incorporado na conta e não a conta é incorporado ao seu nome. Mas mesmo se eu invertesse as classes a dúvida ainda continua.

Mas novamente, sou iniciante e qualquer ajuda é bem vinda.

Obrigado pela ajuda de todos.

Abaixo segue o código. E vocês que são bem mais experientes podem dar umas dicas se meu código ta ok.

public class Cliente {

    private String nome;
    private String endereco;        

    public String getNome(){
        return nome;
    }

    public void setNome(String nomeDoClinete){
        nome = nomeDoClinete;
    }

    public String getEndereco(){
        return endereco;
    }

    public void setEndereco(String enderecoDoCliente){
        endereco = enderecoDoCliente;
    }
}

public class Conta {

    public Cliente titular = new Cliente();
    private double[] historico = new double[50];
    private double totalDaConta = 0;
    private static int identificador = 0;
    private double valorLimite;

    public double[] getHistorico() {
        return historico;
    }

    public void setHistorico(double[] historico) {
        this.historico = historico;
    }

    public double getTotalDaConta() {
        return totalDaConta;
    }

    public void setTotalDaConta(double totalDaConta) {
        this.totalDaConta = totalDaConta;
    }


    public void Cadastrar(String nome, String endereco, double totalDaConta){
        this.titular.setNome(nome);
        this.titular.setEndereco(endereco);
        this.totalDaConta = totalDaConta;
        //historico tbm recebe;
    }

    public void mostrarInformacoes(){
        System.out.println("Informações do Clinte:\n");
        System.out.println("Identificador: " + identificador);
        System.out.println("Nome: " + titular.getNome());
        System.out.println("Endereço: " + titular.getEndereco());
        System.out.println("Total da Conta: " + this.totalDaConta);

        System.out.println("\n");
    }

    public Conta(){
        int numero = this.identificador;
        identificador++;
    }

}

public class Programa {
    public static void main(String[] args) {

        Conta contaTeste = new Conta();

        contaTeste.Cadastrar("Usuario1", "End1", 10.00);
        contaTeste.mostrarInformacoes();

        Conta conta1 = new Conta();
        contaTeste.Cadastrar("Usuario2", "End2", 55.00);
        contaTeste.mostrarInformacoes();
    }
}

Lembrando que alguns métodos parecem não ter sentido, como totalDaConta. É porque é só para fazer os teste de saída.

solução!

Luan, você pode deixar o Cliente como private e criar seu método getter de cliente. Assim, para acessar o nome do cliente, por exemplo, poderia usar

contaTeste.getCliente().getNome();

Carlos, foi isso mesmo que eu fiz. Valeu pela ideia.

E o único jeito mesmo de não conseguir instanciar Cliente na main é colocando dentro de um pacote especifico.