Java multiple constructors with different data types, oke or not, and how to handle?

68 Views Asked by At

I have a class called 'Cell' in which I (think I) need multiple constructors

The goal is to add the cell's later to an excel sheet, when adding to an excel sheet you need to add what type of data to set the excell-cell to and therefor I want to retrieve the data type from the cell class

public Object val;

public Cell (BigDecimal val)
{
    this.val = val;
}

public Cell (String val)
{
    this.val = val;
}

public Cell (int val)
{
    this.val = val;
}

I have 2 questions

  1. How should I store the 'val' parameter, as Object just doesn't seem like the best way to do this?
  2. If I store 'val', how can I later find back what data type 'val' is/was ?

Or am I completely off here and is there a completely different way how I should approach this problem?

3

There are 3 best solutions below

1
Emanuel Trandafir On BEST ANSWER

maybe Cell is too generic in your case. For example, you might consider having different classes for NumericCell and StringCell:

class NumericCell implements Cell {
    private BigDecimal val;

    public NumericCell (BigDecimal val) {
        this.val = val;
    }

    public NumericCell (int val) {
        this(BigDecimal.valueOf(val));
    }
}

class StringCell implements Cell {
    private String val;

    public StringCell (String val) {
        this.val = val;
    }
}

you can keep Cell as an abstract class or interface and put there the common methods you want all the cells to perform, for example

interface Cell {
    String content();
}

now StringCell can implement this and simply return val, while NumericCell knows it operates on a BigDecimal so it can perform some formatting, for example only display 2 decimals and rounding the number:

@Override
public String content() {
    return val.setScale(2, RoundingMode.FLOOR).toString();
}

This is called polymorphism and it is a very powerful tool in OOP. you can read more about it here: https://www.w3schools.com/java/java_polymorphism.asp

0
rbk On

Best way of achieving this is to define a Cell interface and implement multiple classes extending the interface.

public interface Cell {}

Followed by implementation class per cell type:

public class StringCell implements Cell {
    private String value;

    public StringCell(String value){
        this.value = value;
    }
    // ... getters and setters etc
}

You can later find out what type the value is, based on the type of your implementation class.

0
Pinko On

It is not really a good idea to do use generic types to store arbitrary data in a variable if you actually need to perform specific operations on it or need to know what exact data type the variable is currently storing.

You could do a few things to fix it. One idea: use inheritance for your class. I.e. define

public class StringCell extends Cell {
    public String val;

    public StringCell (String val) {
        this.val = val;
    }
    
    // getType() and getValue() function
    // some specific operations for StringCell
}

You could then make the parent class abstract and define a getType() and getValue() function. Since you are using different types, I would not store val in the parent class. Then, if you need specific functions on the data you implement it in the child classes (i.e. addIntCell(IntCell c2) and so on).

This approach lets you also handle arbitrary Strings for your String data. If you only do numeric operations you could also do a type conversion to e.g. BigDecimal (since it has high resolution) and then store another variable type. This can be a value from an Enum. Then, the functions to retrieve values can respect the type variable and get an output accordingly.

IMPORTANT: the output values must be generic/compatible. So even if you know that the variable is String-valued, you should be careful when this value can be retrieved from several sources (i.e. on another instance it yields an integer). So be careful about assumptions and stop for some sanity checks now and then. Specifically, the getValue function mentioned above needs to return the same data type for all subclasses.