3

My question is close to this one but not quite the same.

I have an inherited (as in, I can't/won't change it) array of parameters in my class like so:

public double[] params;

The class utilises these parameters in complex ways, so I would prefer to have human-readable names for each element in the array. In C, you would do something like this

#define MY_READABLE_PARAMETER params[0]

I am also aware that in Java I could create a bunch of constants or an enumerator with attributes. Then, to access a parameter I'd have to type something like this:

params[MY_READABLE_PARAMETER]

This is acceptable but I would really like to omit the array name altogether. Is it possible?

Community
  • 1
  • 1
Naurgul
  • 231
  • 2
  • 9

4 Answers4

3

Yes, it is possible simply by not using an array:

double myReadableParameter;
double anotherReadableParameter;

If you need to access them as a collection, you can always put them in a list.

Karel Petranek
  • 15,005
  • 4
  • 44
  • 68
  • I'd love to do that, but as I said, the array is inherited. I can't mess with the parent class, not least of all because in the general case we don't know how many parameters there are. – Naurgul Jun 08 '11 at 16:53
  • Ok, I think my answer still holds though - you can assign the readable parameters in the constructor of your derived class. – Karel Petranek Jun 08 '11 at 16:56
  • @Naurgul How can you assign names if you don't even know how many parameters you have? – toto2 Jun 08 '11 at 17:00
  • @dark_charlie Wouldn't I store the parameters twice then? – Naurgul Jun 08 '11 at 17:00
  • @toto The parent class doesn't know how many of them there can be, but in the derived class it's specified. This is all for a genetic algorithm, if that helps. So, the parent class is the abstract individual while my own class is the individual for the specific problem I'm solving. – Naurgul Jun 08 '11 at 17:02
  • @Naurgul I guess the original class should have stored the parameters as a `HashMap`. Or even better the parameters could have been put in a special class and you could have had subclasses when you modify the parameter set. But you can't do anything about it now. – toto2 Jun 08 '11 at 17:11
  • @Naurgul: Yes, you would, is that a problem? You won't get around this unless you use Double (as a class) instead of primitive double type. – Karel Petranek Jun 08 '11 at 17:16
  • @dark_charlie Unfortunately, it's a big problem. The application I'm working on will have dozens or hundreds of instances of this class going at the same time. I really can't afford to have everything twice. – Naurgul Jun 08 '11 at 17:20
  • @Naurgul: What are your memory constraints? A double takes 8 bytes, assuming that you will use about 30 parameters and hundreds (let's say 1000) of instances, this means ~235 Kb of memory. – Karel Petranek Jun 08 '11 at 17:33
  • @dark_charlie I have 20 parameters and I don't expect that number to change considerably. I'll try to have as many instances as possible (I don't expect more than 1000 though), but since the processing cost for each is pretty high, maybe you're right that memory isn't the issue. Still, it would take some work to make sure the variables are always in sync with the array. – Naurgul Jun 08 '11 at 17:38
3

Is there any reason you couldn't do this?

...
public double getMyReadableParam() {
    return params[0];
}

public void setMyReadableParam(double value) {
    params[0] = value;
}
...
Ben
  • 6,023
  • 1
  • 25
  • 40
  • Nope, it's certainly doable. I'll consider this. Thanks! – Naurgul Jun 08 '11 at 17:23
  • On second thought, if I have 20 parameters, that means 40 new methods shuffling names around. Not too elegant. – Naurgul Jun 08 '11 at 23:26
  • I agree, 40 new methods would be inelegant. It seems to me that any way you cut it, relying on an arbitrary array of doubles that aren't logically connected lends itself to inelegance; I think you may have to live with some, whatever you end up doing. – Ben Jun 08 '11 at 23:32
3

With Enum:

enum Param {
    AGE(0);
    WEIGHT(1);
    ...

    private int arrayIndex;
    // Constructor
    Param(int index) {
        arrayIndex = index;
    }

    public double getValue(double[] params) {
        return params[arrayIndex];
    }
}

and you use it as such

double age = Param.AGE.getValue(params);

I don't think it is better than the other suggestions, but I wanted to show how to do it with ENUM.

toto2
  • 5,306
  • 21
  • 24
  • Actually, something like an enum or a constant like public static int THE_ANSWER_TO_LIFE_THE_UNIVERSE_AND_EVERYTHING = 42; – Joe Plante Mar 08 '13 at 15:52
  • Oops. Didn't finish the last comment. Anyways, the public static constant and the enum are the common practise, and I think the enum is seen to be a little better – Joe Plante Mar 08 '13 at 16:29
1

If you have an array of doubles and each array element in a specific position has a definite meaning you should create a class instead.

public class MyParamBlob extends ParentParamBlob
{
    private double myReadableParameter;
    private double anotherParameter;
    private double yetOneMore;

    // getters and setters as appropriate
}

If you need to deal with an existing double[] from "outside" you could have a constructor and/or a method that takes an array as a parameter.

public class MyParamBlob
{
    ...
    public MyParamBlob(double[] values)
    {
        setAll(values);
    }
    // getters and setters as appropriate
    ...
    public void setAll(double[] values)
    {
        myReadableParameter = values[0];
        anotherParameter = values[1];
        // etc.
    }
}

Edit - to explain my comment

If the original parent class that this is a subclass of (the reason the double[] exists in the first place) has a getter for the array, that could be overridden in this class, building and returning the array when requested -- e.g.

public double[] getParams()
{
    double[] params = new double[4];
    params[0] = myReadableParameter;
    params[1] = anotherParameter;
    // etc.
}

If the array is directly accessible from an instance of the parent class, without a getter, e.g. myArray = parentInstance.params or double d2 = parentInstance.params[2] then (1) that's a bad design and (2) callers could change the array values out from under you parentInstance.params[1] = 0.0;

Stephen P
  • 14,422
  • 2
  • 43
  • 67
  • Wouldn't your second solution lead to storing the data two times? Once in values and once in MyParamBlob's fields. – Naurgul Jun 08 '11 at 16:58
  • I don't think the storage space matters. Anyway, any solution you have will take some memory. However, the danger with having two copies of the parameters is that you can make big errors when you try to assing them new values. – toto2 Jun 08 '11 at 17:14
  • @Naurgul - no, notice the array is a parameter passed in and *not* stored; only the values in it are stored. What really matters, and pertaining to toto's comment, is whether or not the array is accessible in the parent class, either via `public double[] getParams()` or directly `parentThing.params[2]` in which case you may have to synchronize the array with the instance members. But for `getParams()` you could build and return the array *when requested* ... see my edit. – Stephen P Jun 08 '11 at 22:19
  • I like the idea of overriding the methods to make it seem like there's an array when there's none. However, in the parent class the array is public but it also has a getter/setter pair. I'm not sure what is used to interact with the class outside my own code. I'm also not sure what you mean by saying "callers could change the array values out from under you parentInstance.params[1] = 0.0;". – Naurgul Jun 08 '11 at 22:57