Inheritance, polymorphism and access to methods

I have 3 classes and 1 enum:

public class Pessoa {
        private TipoPessoa tipo;
        public TipoPessoa getTipo() {
            return tipo;
        }
        public void setTipo(TipoPessoa tipo) {
            this.tipo = tipo;
        }
      }



public class PessoaF  extends Pessoa{
                private String cpf;
                public String getCpf() {
                    return cpf;
                }
            public void setCpf(String cpf) {
                this.cpf = cpf;
            }
         }



public class PessoaJ extends Pessoa{
            private String cnpj;
            public String getCnpj() {
                return cnpj;
            }
            public void setCnpj(String cnpj) {
                this.cnpj = cnpj;
            }
        }



public enum TipoPessoa {
            PESSOAFISICA, PESSOAJURIDICA;
        }

I want when setting a person type, to be able to create an instance equivalent to the enumerator applied to the type:

For example, if the sector was a physical person, I would be able to access the members (attributes, fields, and methods) of the personal class because it would call the correct constructor:

Pessoa p1 = new PessoaF();
p1.setCpf = 32443265332;

But with inheritance I cannot access the members of a child class through an instance created from a Pai class. So how to proceed?

I modified the enum, implementing an abstract method that returns me the constructor I want to use according to the type of person set:

public enum TipoPessoa {
    PESSOAFISICA (0, "Pessoa Fisica") {
        @Override
        public Pessoa obterPessoa() {
            return new PessoaF();
        }
    },
    PESSOAJURIDICA (1, "Pessoa Juridica") {
        @Override
        public Pessoa obterPessoa() {
            return new PessoaJ();
        }
    };



    public abstract Pessoa obterPessoa();


    private TipoPessoa(){}
    private TipoPessoa(Integer cod, String desc) {
        this.cod = cod;
        this.desc = desc;
    }

    private Integer cod;
    private String desc;
    public Integer getCod() {
        return cod;
    }
    public void setCod(Integer cod) {
        this.cod = cod;
    }
    public String getDesc() {
        return desc;
    }
    public void setDesc(String desc) {
        this.desc = desc;
    }
 }

With this modification I am creating the object as follows:

Pessoa p1 = TipoPessoa.PESSOAFISICA.obterPessoa();

When I request it to print the type of the created object it tells me that it created correctly:

 System.out.println(p1.getClass());
 Retorno : class Pessoas.PessoaF

But still I can not access the method setCpf() that is inside the Class PessoaF.

I want create a person and according to the value set in the type attribute. And that this created object can access the members according to the option of the selected enumerator. How to proceed?

Class diagram

Author: Maniero, 2018-03-25

1 answers

I think you want to create a instanceand not a resort.

I don't like the term attribute, I prefer field.

You can access all public members of the object type at that time. You cannot access the members of a type that is part of that object but is not the type being used at that time. If the type is the parent, it can only access its members, it cannot access the members of the child type.

If you can ensure that the object is of type child can do a cast, which is a type conversion (it doesn't necessarily change something in the data, it just tells the compiler that it wants to use a more specialized type. There it is allowed to access the members of the child type, and of the parent also because the child always has everything that the parent has.

In general if the cast fails it will generate an error or the result will be a null. There are cases that the compiler will be able to identify that it is not possible and does not even let compile.

In this example it does not make much sense to declare p1 as Pessoa if you know you need it as PessoaFisica, but it is possible, then you can write:

((PessoaFisica)p1).cpf

Performance will be worse if there is no optimization that the compiler is prepared to do.

Can also be done with reflection, but it is absurdly worse and disproportionate.

Just because a tool solves what you wanted doesn't mean it's right use it.

Wrong tool for the task-horse inside an ordinary car

 5
Author: Maniero, 2018-03-26 14:14:38