我有一个超类生物,除了其他人之外我还有以下变量:
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中做额外的逻辑?或者这是不好的形式?解决这个问题的最佳方法是什么?
答案 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.
}
<强>更新强>: 还要考虑
施工期间设置地形。应该在构造函数中完成的常常工作是在setter中完成的。为了避免混乱,帮助重用,您还可以使用validateTerrain()方法验证构造函数和setter中的输入。所以构造函数看起来像
//就像有人提到的枚举是一个不错的选择
public Creature(int ter)
{
//setter can set the value same way
if (validateTerrain(ter)) {
terrain = ter;
}
}
如果'terrain的值在包含它的对象的生命周期内不会改变,则摆脱setter(这需要#1)。这将使该属性在构造后为只读。无论这一步如何,#1都应该以IMO完成。
答案 4 :(得分:1)
没有什么可以阻止你把任何你想要的东西放在吸气剂或制定者身上。这是你的代码;你控制它了。
然而,那些if语句是赋值,而不是比较。我想你正在寻找==,而不是=。