How to call the same method with different arguments but inherit from the same parent class?

1

I have two classes ( ColunaDoGrafico and ColunaDoRelatorio ) that extend from Coluna .

My Column class has the following structure:

public class Coluna  {
    protected String tipoFiltro;
    protected boolean exibeFiltro;
    protected Relatorio relatorio;

    // alguns outros atributos

    //getters e setters
}

The Report class is basically composed of:

public class Relatorio {
    private Set<ColunaDoRelatorio> colunasDoRelatorio;
    private Set<ColunaDoGrafico> colunasDoGrafico;

    // outros atributos

    public Set<ColunaDoRelatorio> getColunasDoRelatorio() {
        return colunasDoRelatorio;
    }

    public void setColunasDoRelatorio(Set<ColunaDoRelatorio> colunasDoRelatorio) {
        this.colunasDoRelatorio = colunasDoRelatorio;
    }

    public Set<ColunaDoGrafico> getColunasDoGrafico() {
        return colunasDoGrafico;
    }

    public void setColunasDoGrafico(Set<ColunaDoGrafico> colunasDoGrafico) {
        this.colunasDoGrafico = colunasDoGrafico;
    }
}

The GraphPad and RowData classes inherit from Column and have other attributes unique to each.

They are basically:

public class ColunaDoGrafico extends Coluna {

    private String apresentacao;
    private boolean eixoY;
    private boolean eixoX;
    private String operacao;
    //getters and setters
}

e:

public class ColunaDoRelatorio extends Coluna{
    private boolean exibeNoRelatorio;
    private String operacao;
    private String clausula;
    //getters and setters
 }

In another class I have a method that must go through a set of columns, which may be a Set and sometimes a Set. And this method should analyze two attributes (which are common to both child classes, since it was inherited from the parent class) of each of the items in that list. I'm doing it this way:

private void trataFiltro(Set<Coluna> colunas){
    StringBuilder sb = new StringBuilder();
    sb.append(query);
    for(Coluna coluna: colunas){
        if(coluna.isExibeFiltro()){
            if(coluna.getTipoFiltro().equals("texto")){
                System.out.println("A");
            }else if(coluna.getTipoFiltro().equals("dominio")){
                System.out.println("B");            
            }else if(coluna.getTipoFiltro().startsWith("tempo")){
                System.out.println("C");
            }else {
                System.out.println("D");
            }
        }
    }
}

However, when I try to call the method as follows:

trataFiltro(relatorio.getColunasDoRelatorio());

or

trataFiltro(relatorio.getColunasDoGrafico());

It's not compiling and says:

  

The method is setFilter (Set) is not applicable for the arguments Set

Because both classes have the attributes that are required by the method, should not the code work? How can I solve this? I have to write the same method for each of the classes, changing only the argument?

    
asked by anonymous 03.04.2018 / 21:01

3 answers

2

Complementing the Dudaskank response , the reason why Set<? extends Coluna> resolves is because a Set<Coluna> is an object in which these two properties are worth:

  • We can get items of type Coluna . This is what you want.
  • We can add items like Coluna to it. This is not something you wanted.
  • It is because of this second property that Set<ColunaDoGrafico> and Set<ColunaDoRelatorio> are not compatible with Set<Coluna> . You can not add any type of Coluna within a Set<ColunaDoGrafico> for example.

    The second property is not something you want. You can give it away with Set<? extends Coluna> . In this case only the first property is worth.

    Similarly, if you want to give up the first property and only the second property, you would use Set<? super Coluna> .

        
    03.04.2018 / 23:15
    2

    Change the method signature to:

    private void trataFiltro(Set<? extends Coluna> colunas)
    

    According to the user's explanation utluiz ♦ in another answer , this is called covariance:

      

    Just to contextualize, covariance occurs when we use extends and we allow a more specific type (subclass) to be used instead of a more generic type.

        
    03.04.2018 / 21:20
    0

    Overload the method, ie make a method with the same signature but which requires different arguments to execute, or no argument, following the example of a class for data manipulation with the database:

    package mainFiles;
    
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.SQLException;
    import java.util.ArrayList;
    import java.util.logging.Level;
    import java.util.logging.Logger;
    
    public abstract class DataBaseHandler {
    
        public abstract boolean create(String field) throws SQLException;
        public abstract ArrayList<ArrayList<String>> read(boolean isOriginal) throws SQLException; //Repare que aqui existe um método que requer um argumento do tipo boolean.
        public abstract ArrayList<ArrayList<String>> read() throws SQLException; //Repare que existe um mesmo método mas que pede argumentos diferentes.
        public abstract boolean update(String field, String values[]) throws SQLException;
        public abstract boolean delete(String field) throws SQLException;
    
        public Connection dbConfig(Object dbData[]) {
            System.out.println("Iniciando processo de configuração.");
            try {
                System.out.println(dbData[0].toString() + " " + dbData[1].toString() + " " + dbData[2].toString());
                Class.forName("oracle.jdbc.OracleDriver");
                Connection dbConfiguredConn = DriverManager.getConnection(dbData[0].toString(), dbData[1].toString(), dbData[2].toString());
                System.out.println("Banco configurado com sucesso!");
                return dbConfiguredConn;
            } catch (SQLException | ClassNotFoundException ex) {
                System.out.println("Erro ao conectar com o banco.");
                Logger.getLogger(Classifier.class.getName()).log(Level.SEVERE, null, ex);
                return null;
            }
        }
    }
    

    However, just as you will have to override the method that requires the argument, you will have to override that which does not require any. If you call them, just use the same signature, and pass different parameters, or no parameters depending on how you created the overloads.

        
    04.04.2018 / 01:29