1

I have a class that has about 20 attributes which can be devided in 10 groups having two attributes of type minValue and maxValue.

I am wondering how to define the object's constructor. I have two options:

First one,

public myClass(minValueType1, maxValueType1, minValueType2,maxValueType2,....,minValueType10, maxValueType10) 

Second one,

public myClass(type1Arr[],type2Array[],......,type10Array[])

where each array has length of 2 with minValue and maxValue.

Which way do you think is better?

Sazzadur Rahaman
  • 6,938
  • 1
  • 30
  • 52
Joro Seksa
  • 1,525
  • 3
  • 18
  • 44
  • 4
    Why don't you have a single type representing the combination "min and max"? It would make things much simpler. – Jon Skeet May 18 '13 at 16:32
  • I don't think it is neccesery because there are no functions associated with these types. – Joro Seksa May 18 '13 at 16:34
  • 2
    If it's a min and a max, my gess is that the code tests is some variable is >= min and <= max, which would justify the creation of a `Range` class with an `contains(int value)` method. Even without this method, grouping min and max together makes sense and justifies the creation of this class. – JB Nizet May 18 '13 at 16:41
  • 1
    @JoroSeksa: That's got nothing to do with it. If you have pairs of related values, that pairing is something to encapsulate in itself, so you can represent the idea of "the minimum and maximum speed" (for example) in a single value. I'd argue that you *could* also add useful methods to that type - such as validating a value - but that's a different matter. – Jon Skeet May 18 '13 at 17:10

8 Answers8

4

Here is one way

class MyClass
{
  private Map<String, MinMax> others;
  public MyClass(Map<String, MinMax> in)
  {
    others=in;
  }
}

class MinMax
{
  private int min;
  private int max;

  public boolean isWithinRange(int input)
  {
    return input >= min && input <= max;
  }
}
Aravind Yarram
  • 78,777
  • 46
  • 231
  • 327
  • ok, but how do i know for example minFuelPerHour and maxFuelPerHour or minAccumulatorValue and maxAccumulatorValue where in the list are? – Joro Seksa May 18 '13 at 16:39
  • 1
    @JoroSeksa Then use Map (one option). updated my answer. Use String keys like "fuelPerHour", "accumulatorValue" etc. – Aravind Yarram May 18 '13 at 16:41
1

You can have a class with two attributes(min,max) and a EnumType (EnumType with 10 fields)

Sanjaya Liyanage
  • 4,706
  • 9
  • 36
  • 50
1

I would recommend a builder pattern. There's another SO post on the subject here. That way you can keep your constructor simple while allowing for the construction of an immutable object if you so desire.

lealand
  • 367
  • 4
  • 13
1

A HashSet<?,MinAndMax<?>> may be more flexible and easier to use.

Goofy
  • 431
  • 5
  • 7
1

to simplify things you can create a class as below

public class Value {
  private int max;
  private int min;

  public Value(int min, int max) {
    this.min = min;
    this.max = max;
  }

  public int getMax() {
    return max;
  }

  public int getMin() {
    return min;
  }
}

public class YourClass {

  // as all the values are same type
  // we can set data inside a Map, 
  // where String will be property name for each min and max type
  private Map<String, Value> data;

  public YourClass(Map<String, Value> data) {
    this.data = data;
  }

  public Map<String, Value> getData() { 
    return data;
  }
}
S4beR
  • 1,872
  • 1
  • 17
  • 33
0

A class ValueType with 2 attributes (min, max) and then a constructor with just one parameter : an array of ValueType

Thierry
  • 5,133
  • 3
  • 25
  • 30
0

You could either parametrize Collections (see Pangea's answer), or use an empty constructor, default values, and setters returning this, a bit like in StringBuilder.

Here's my example for the latter:

package test;

public class Main {

    private String myString = "";
    private Integer myInteger = 0;
    // etc...

    public Main() {

    }
    public Main setString(String value) {
        // TODO check value
        myString = value;
        return this;
    }
    public Main setInteger(Integer value) {
        // TODO check value
        myInteger = value;
        return this;
    }
    @Override
    public String toString() {
        return "My String is: " + myString + " and my Integer is: " + myInteger;
    }
    public static void main(String[] args) {
        System.out.println(new Main().setString("foo").setInteger(1).toString());
    }
}
Mena
  • 47,782
  • 11
  • 87
  • 106
0

You simply should not have a constructor with 20 arguments. Try to introduce a parameter object and / or use a (wrapped) Collection.

How about a List<Range<T>>, a Map<Class, Range> or a RangeConstraints class that is responsible for checking the validity of values?

Links:

When a method has too many parameters?

best practice for passing many arguments to method?

http://www.refactoring.com/catalog/introduceParameterObject.html

Community
  • 1
  • 1
Jens Piegsa
  • 7,399
  • 5
  • 58
  • 106