How to call the same method with different arguments but inherited from the same mother class?

Asked

Viewed 110 times

1

I have two classes (ColunaDoGrafico and ColunaDoRelatorio) extending 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 consists basically 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 classes Colunadografico and Colunadorelatorio inherit from Coluna and have other particular attributes to each one.

Are basically:

public class ColunaDoGrafico extends Coluna {

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

and:

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 should go through a set of columns, which can now be a Set and can now be a Set. And this method should analyze two attributes (which are common to both daughter classes, since it was inherited from the mother class) from 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 in the following way:

trataFiltro(relatorio.getColunasDoRelatorio());

or

trataFiltro(relatorio.getColunasDoGrafico());

It’s not compiling and it says :

The method trataFiltro(Set) is not applicable for the Arguments Set

Because both classes have the attributes that are required for the method, shouldn’t the code work? How do I fix this? I have to write the same method for each class, changing only the argument?

  • 1

    Add the two missing classes as well.

  • I’ve already added :)

  • 1

    Missed the gets involved in the error.

  • put the report class gets and sets

  • The error is certainly not in the code presented. Where does this method come from? Please place the complete classes or if it is too big, make a [mcve], with pieces not even to simulate the problem.

3 answers

2

Change the method signature to:

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

According to user explanation utluiz in another answer, This is called covariance:

Just to put it in context, covariance occurs when we use extends and allow a more specific type (subclass) to be used in place of a more generic type.

  • It worked! If you can explain why, I’d be grateful!

  • 1

    It worked because that way you force yourself to accept all subtypes(daughter class) of the column class, and not just the column class, as Oce was doing.

  • Ahhhh, one more to my knowledge! thank you!

  • 2

    @Tathianaianelli Her name is covariance

  • But this is strange, because if the method received only one column, instead of a set of columns, it would work normally. private void trataFiltro(Coluna c) he would accept both types of columns.

  • even so, thanks for the help Articuno, also did not know the term

Show 1 more comment

2


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

  1. We can obtain items of the type Coluna. That’s what you want.
  2. We can add items like Coluna. 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’t add any kind of Coluna within a Set<ColunaDoGrafico> for example.

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

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

0

Overload the method, that is, make a method with the same signature but require different arguments for it to be executed, or no argument, follow the example of a class focused on 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 overwrite the method that requires the argument, you will have to overwrite what requires none. If calling them, just use the same signature, and pass different parameters, or no parameters depending on how you created the overloads.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.