【问题标题】:In which situation to declare instance variable?在什么情况下声明实例变量?
【发布时间】:2014-06-20 09:33:32
【问题描述】:

我有简单的课程:

class Blah { 

  private PApplet applet; 
  private float value;

  public Blah(PApplet theApplet, theValue) {
    applet = theApplet;
    value = theValue;
  }

  public float getX() {
    return PApplet.map(value, applet.min, applet.max, applet.c1, applet.c2);
  }

}

我现在想知道,是否可以像描述的那样拥有getX()

我不应该声明一个变量xpos 和一个setter 和getter 吗? 在这种情况下,我如何决定是否应该声明一个实例变量? (其中一个实例变量值依赖于另一个实例变量)

使用xpos 实例变量,我将拥有:

class BlahBla {
  private PApplet applet;
  private float value;
  private float xpos;

  BlahBla(PApplet theApplet, float theValue) {
    applet = theApplet;
    value = theValue;
    xpos = PApplet.map(theValue, applet.min, applet.max, applet.c1, applet.c2);
  }

  public getX() {
    return xpos; 
  }

  public setX(float theValue) {
    xpos = map(theValue, applet.min, applet.max, applet.c1, applet.c2);
  }

}

xpos 作为实例变量的优势:

  • 我不会在每次调用 getX() 时都进行映射

xpos 作为实例变量的缺点:

  • 更多代码
  • 使用 setter 方法时的困惑

注意事项:

  • setter 不应该将值直接分配给xpos吗?这里应该允许任何操作(如映射)吗?

  • xpos 应该链接到value - 不带参数创建setX() 是否有效?如果我将xpos 变量和set(float theValue) 设置为public - 这会破坏xposvalue 之间的链接,因为使用setter 允许分配value 以外的任何数据。

【问题讨论】:

  • 您的原始实现不需要 setter,仅仅因为添加了 getter 并不意味着您需要 setter。如果某些东西永远不应该改变,请不要提供 setter
  • 假设 xpos 没有改变,从效率的角度来看,将其保留为一个字段是有意义的,但从良好的标准角度来看,如果您按需创建 xpos、延迟加载,则几乎没有什么区别它或在构造对象时创建

标签: java oop processing instance-variables


【解决方案1】:

拥有一个字段和一个 getter 的主要优点是它将充当缓存系统,这样您就不会一次又一次地计算相同的值(这可能很好,因为它可能会很糟糕,具体取决于你正在做)。缺点是它会导致代码不太清晰,如果你的值很大,它会消耗更多的内存。

对我来说,你应该使用一个字段和一个 getter(如果不改变值,则不要使用 setter,记住打开/关闭原则),但这又取决于你打算如何使用你的类。

另外,是的,您可以在 setter 中执行诸如映射之类的操作,这实际上就是您应该使用 setter 的原因:您不允许直接访问您的字段,因此您对字段修改有一个控制点,可用于执行操作在参数上(例如检查它们的空值)

【讨论】:

    【解决方案2】:

    根据您的第一个版本,只有一个 getter:没有字段:

    • 更简单的代码
    • 不必担心value等对象生命周期发生变化的情况(今天可能不会发生,但可能有一天会发生)
    • 更少的代码
    • 这是过早的优化:

    将计算属性存储在字段中的唯一原因是“性能”,但如果您在设计时考虑它本身就是一个大错误。仅当您有确凿证据确实存在性能问题时才考虑使用字段。另外,如果你只为某些对象调用 getter,那么为所有对象计算它是一种浪费。

    在这两种情况下都没有必要或没有意义。

    【讨论】:

    • 关于您的评论,我需要指定一件事 - 第一个版本中的 getX() 在显示对象时调用(60 fps),此外还有其他方法,例如检查对象是否在一个屏幕(如果它移动)等等。所以我认为在 getX() 方法中执行映射并不好......到目前为止性能还可以,但这是一个好习惯吗?我认为每当我有 x 字段时,它的 getter 应该始终指向 x,没有任何突变......
    • 嗯 ar 60 fps 似乎它可能是缓存的候选者,如果您决定这样做,请创建一个私有 setX() 方法来创建和设置计算字段并从您的设置器中调用它值影响计算值的其他字段。即便如此,如果它按原样执行,我会离开它并做其他工作。 getter 返回计算值是可以的。 getter 不能修改状态。保存返回的值是缓存,不被视为“修改状态”。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-18
    • 2020-09-17
    • 2012-11-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多