【问题标题】:Equivalent of #define in Java for macros相当于 Java 中的 #define 用于宏
【发布时间】:2011-09-11 01:17:32
【问题描述】:

我的问题与this one 很接近,但并不完全相同。

我的类中有一个 inherited(如,我不能/不会更改它)参数数组,如下所示:

public double[] params;

该类以复杂的方式使用这些参数,因此我希望数组中的每个元素都具有人类可读的名称。在 C 中,你会做这样的事情

#define MY_READABLE_PARAMETER params[0]

我也知道在 Java 中我可以创建一堆常量或带有属性的枚举器。然后,要访问参数,我必须输入如下内容:

params[MY_READABLE_PARAMETER]

这是可以接受的,但我真的很想完全省略数组名称。有可能吗?

【问题讨论】:

  • 有各种支持 C 风格宏的 Java 预处理器
  • @Jochen 这样的情况会不会有点矫枉过正?
  • 矫枉过正? C 预处理器正在做同样的“矫枉过正”……
  • @Jochen 我的意思是我必须安装一个额外的库才能获得这个小小的便利。如果它是必备的并且我需要一个复杂的宏,那么我想它会很好。

标签: java preprocessor c-preprocessor


【解决方案1】:

是的,只需不使用数组即可:

double myReadableParameter;
double anotherReadableParameter;

如果您需要将它们作为一个集合来访问,您可以随时将它们放在一个列表中。

【讨论】:

  • 我很乐意这样做,但正如我所说,数组是继承的。我不能弄乱父类,尤其是因为在一般情况下我们不知道有多少参数。
  • 好吧,我认为我的回答仍然成立——您可以在派生类的构造函数中分配可读参数。
  • @Naurgul 如果您甚至不知道您有多少个参数,您如何分配名称?
  • @dark_charlie 那我不把参数存储两次吗?
  • @toto 父类不知道可以有多少个,但是在派生类中是指定的。如果有帮助,这一切都适用于遗传算法。因此,父类是抽象个体,而我自己的类是我正在解决的特定问题的个体。
【解决方案2】:

你有什么理由不能这样做吗?

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

public void setMyReadableParam(double value) {
    params[0] = value;
}
...

【讨论】:

  • 不,这当然是可行的。我会考虑这个。谢谢!
  • 再想一想,如果我有 20 个参数,那意味着 40 个新方法会改变名称。不太优雅。
  • 我同意,40 种新方法会很不优雅。在我看来,任何你削减它的方式,依赖于逻辑上没有连接的任意双精度数组都会导致不优雅;我想你可能不得不忍受一些,无论你最终做什么。
【解决方案3】:

Enum:

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

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

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

你就这样使用它

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

我不认为它比其他建议更好,但我想展示如何使用 ENUM 来做到这一点。

【讨论】:

  • 实际上,类似枚举或常量之类的东西 public static int THE_ANSWER_TO_LIFE_THE_UNIVERSE_AND_EVERYTHING = 42;
  • 糟糕。没有完成最后的评论。无论如何,公共静态常量和枚举是常见的做法,我认为枚举看起来要好一些
【解决方案4】:

如果你有一个双精度数组,并且特定位置的每个数组元素都有明确的含义,你应该创建一个类。

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

    // getters and setters as appropriate
}

如果您需要从“外部”处理现有的double[],您可以使用构造函数和/或将数组作为参数的方法。

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.
    }
}

编辑 - 解释我的评论

如果这是子类的原始父类(首先存在 double[] 的原因)具有数组的 getter,则可以在此类中覆盖它,在请求时构建并返回数组 - - 例如

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

如果数组可以从父类的实例直接访问,没有getter,例如myArray = parentInstance.paramsdouble d2 = parentInstance.params[2] 然后(1)这是一个糟糕的设计,(2)调用者可以从你下面更改数组值 parentInstance.params[1] = 0.0;

【讨论】:

  • 您的第二种解决方案不会导致数据存储两次吗?一次在值中,一次在 MyParamBlob 的字段中。
  • 我认为存储空间并不重要。无论如何,您拥有的任何解决方案都会占用一些内存。但是,拥有两个参数副本的危险在于,当您尝试为它们分配新值时可能会犯大错误。
  • @Naurgul - 不,注意数组是传入的参数并且没有存储;仅存储其中的值。真正重要的是,与 toto 的评论有关的是,数组是否可以在父类中访问,通过public double[] getParams() 或直接parentThing.params[2] 在这种情况下,您可能必须将数组与实例成员同步。但是对于getParams(),您可以构建并返回数组当请求时 ...查看我的编辑。
  • 我喜欢重写方法以使其看起来像没有数组时的想法。但是,在父类中,数组是公共的,但它也有一个 getter/setter 对。我不确定在我自己的代码之外使用什么与类进行交互。我也不确定你说“调用者可以从你的 parentInstance.params[1] = 0.0; 下更改数组值”是什么意思。
猜你喜欢
  • 2010-12-28
  • 2011-12-06
  • 2016-07-24
  • 2012-08-25
  • 2010-12-11
  • 1970-01-01
  • 2013-05-09
相关资源
最近更新 更多