我可以在getter / setter中执行其他逻辑吗?

时间:2014-01-14 00:41:15

标签: java setter getter

我有一个超类生物,除了其他人之外我还有以下变量:

    public int terrain;
    public static final int DESERT = 0;
    public static final int MOUNTAIN = 1;
    public static final int FOREST = 2;

我想按照以下方式做点什么:

    public int getTerrain(){
        if(terrain = 0){
            terrain = DESERT;
        }
        if(terrain = 1){
            terrain = MOUNTAIN;
        }
        if(terrain = 2){
            terrain = FOREST;
        }
        return terrain;
    }

    public void setTerrain(int terrain){
        if(terrain = 0){
            this.terrain = DESERT;
        }
        if(terrain = 1){
            this.terrain = MOUNTAIN;
        }
        if(terrain = 2){
            this.terrain = FOREST;
        }

        this.terrain = terrain;
    }

这不起作用,但有没有办法可以在我的getter / setter中做额外的逻辑?或者这是不好的形式?解决这个问题的最佳方法是什么?

5 个答案:

答案 0 :(得分:9)

这不起作用的原因是因为你这样做

if(terrain = 1)

而不是

if(terrain == 1)

作业使用=,比较使用==

话虽如此:我会选择一个枚举。

public enum Terrain {
    DESERT,
    MOUNTAIN,
    FOREST
}

用法:

public class Main {
    private Terrain terrain;

    public static void main(String[] args) {
        Main obj = new Main();
        obj.setTerrain(Terrain.DESERT);
    }

    public Terrain getTerrain(){
        return terrain;
    }

    public void setTerrain(Terrain terrain){
        this.terrain = terrain;
    }
}

您仍然可以使用数值作为别名。

关于getter / setter应包含的内容:是的,您可以在其中执行逻辑。使用getter / setter背后的整个想法是,您可以在返回数据之前提供其他逻辑(如验证或操作支持字段)。

答案 1 :(得分:3)

除了比较器问题(double-equals vs single-equals)之外,您可以解决的代码还有一些其他问题可能会澄清getter和setter的作用。您实际上不需要在任何一种方法中进行任何比较。

如果我们声明MOUNTAIN总是等于1 - 那么“1”和“MOUNTAIN”可以在我们的代码中互换使用。让我们用常量名替换所有的数字文字(0,1,2)。

public void setTerrain(int terrain){
    if(terrain == DESERT){
        this.terrain = DESERT;
    }
    if(terrain == MOUNTAIN){
        this.terrain = MOUNTAIN;
    }
    if(terrain == FOREST){
        this.terrain = FOREST;
    }
}

这有点多余。实际上,如果我们用数字替换地形类型,问题可能会更明显:

public void setTerrain(int terrain){
    if(terrain == 0){
        this.terrain = 0;
    }
    if(terrain == 1){
        this.terrain = 1;
    }
    if(terrain == 2){
        this.terrain = 2;
    }
}

想象一下,如果你有1000种地形类型 - 代码会爆炸甚至更多。

public void setTerrain(int terrain){
    if(terrain == 0){
        this.terrain = 0;
    }
    if(terrain == 1){
        this.terrain = 1;
    }
    if(terrain == 2){
        this.terrain = 2;
    }
    if(terrain == 3){
        this.terrain = 3;
    }
    ...
    if(terrain == 999){
        this.terrain = 999;
    }
    if(terrain == 1000){
        this.terrain = 1000;
    }
}

相反,你可以使用这样的东西:

public void setTerrain(int terrain){
    this.terrain = terrain;
}

正如Dino的回答所示,添加输入验证总是一个好主意,以处理有人发送的数字不是您支持的地形之一的情况:

public void setTerrain(int terrain){
    if (terrain < 0 || terrain > 2) {
        System.out.println("Invalid terrain number!");
    } else {
        this.terrain = terrain;
    }
}

同样,您只需直接返回您的Creature的地形类型即可简化您的吸气剂 - 无需进行比较!

public int getTerrain(){
    return this.terrain;
}

答案 2 :(得分:2)

您使用了赋值运算符=,因此不会进行比较。看起来您为此代码收到编译器错误,因为boolean没有if值。

if(terrain = 0){

您想比较这些值,因此请使用相等比较运算符:

if(terrain == 0){

同样适用于您的其他比较。

话虽如此,你的setter方法中的“额外逻辑”并没有错。实际上,这是在对象中提供封装和数据完整性的首选方式。您可以更进一步,为IllegalArgumentException值突发int,或者您可以定义并使用enums来防止意外值。

答案 3 :(得分:2)

是的,你可以。

除了“=”,“==”混淆了你的代码(这就是为什么它可能不起作用)你在setter和getter中都设置了值。虽然没有什么可以阻止你这样做,但这样做是不对的。此外,您应该考虑初始化“地形”,例如

public int terrain = DESERT;而不是

public int terrain;

这样你的getter可以简化为

public int getTerrain() { return terrain; }

你的二传手中的逻辑也没有多大意义。你可能想要这样的东西

public void setTerrain(int ter)
{
   //validate input. You could do a full invalid range check although 
   //I just checked here for negative values
   if (ter < 0) {
   //handle this use case. You want to validate input for public API of a class always.
   }
   //set value.
   terrain = ter;

   //Compare with the finals here and do whatever else needs to be done.
}

<强>更新: 还要考虑

  1. 施工期间设置地形。应该在构造函数中完成的常常工作是在setter中完成的。为了避免混乱,帮助重用,您还可以使用validateTerrain()方法验证构造函数和setter中的输入。所以构造函数看起来像

    //就像有人提到的枚举是一个不错的选择

    public Creature(int ter) { //setter can set the value same way if (validateTerrain(ter)) { terrain = ter; } }

  2. 如果'terrain的值在包含它的对象的生命周期内不会改变,则摆脱setter(这需要#1)。这将使该属性在构造后为只读。无论这一步如何,#1都应该以IMO完成。

答案 4 :(得分:1)

没有什么可以阻止你把任何你想要的东西放在吸气剂或制定者身上。这是你的代码;你控制它了。

然而,那些if语句是赋值,而不是比较。我想你正在寻找==,而不是=。