首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >设置类变量的最好方法是什么?它是一个基于java中依赖枚举的条件逻辑的枚举。

设置类变量的最好方法是什么?它是一个基于java中依赖枚举的条件逻辑的枚举。
EN

Stack Overflow用户
提问于 2018-10-10 08:53:08
回答 5查看 815关注 0票数 4

我试图根据一些计算或条件逻辑将值从一个枚举映射到另一个枚举,我需要执行这些计算或条件逻辑来为类变量设置正确的枚举值。如何才能在不使用太多if/else、switch语句的情况下做到这一点?

代码语言:javascript
复制
Enum BRAND {
 MINI, FERRARI, PAGANI
}

和另一个枚举

代码语言:javascript
复制
Enum ENGINE {
LEVEL1, LEVEL2, LEVEL3
}

我有一个这样的类:

代码语言:javascript
复制
Class Car() {

 int model;
 int year;
 Engine engine;

 // I want to calculate set the engine depending on the brand based on conditional logic
 public carEngineCalculator (Brand b) {
   Car mycar = new Car();

   if (mycar.isSuperCar(b) {
    if (mycar.isCrazyGood(b)) {
        mycar.engine = ENGINE.LEVEL1;
    } else {
        mycar.engine = ENGINE.LEVEL2;
    }
   } else {
    mycar.engine = ENGINE.LEVEL3;
   }
   ... //And the conditions can be more complex
 }

 public boolean isSuperCar(Brand b) {
    if (b.FERRARI || b.PAGANI) {
     return true;
    } 
    return false;
 }

 public boolean isCrazyGood(Brand b) {
    return ...;
 }
} 

可能有不止一个这样的条件需要检查才能设置值,我希望避免上面显示的令人讨厌的if/else/switch语句。有没有更实用的方法来做这件事。

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2018-10-19 17:20:46

如我所说,使用谓词将如下所示:

代码语言:javascript
复制
public enum Brand {
    MINI,
    FERRARI,
    PAGANI
}

public enum Engine {
    LEVEL1,
    LEVEL2,
    LEVEL3
}

public class Entry {
    public final Predicate<Car> pred;
    public final Engine engine;

    public Entry(Predicate<Car> pred, Engine engine) {
        this.pred = pred;
        this.engine = engine;
    }
}

public class Car {
    int model;
    int year;
    Engine engine;

    public void carEngineCalculator(Brand b) {
        Car mycar = new Car();

        List<Entry> cases = new ArrayList<>();
        cases.add(new Entry(c -> c.isSuperCar(b) && c.isCrazyGood(b), Engine.LEVEL1));
        cases.add(new Entry(c -> c.isSuperCar(b) && !c.isCrazyGood(b), Engine.LEVEL2));
        cases.add(new Entry(c -> !c.isSuperCar(b), Engine.LEVEL3));

        mycar.engine = cases.stream().filter(x -> x.pred.test(mycar)).findFirst().get().engine;

    }

    public boolean isSuperCar(Brand b) {
        if ((b == Brand.FERRARI) || (b == Brand.PAGANI)) {
            return true;
        }
        return false;
    }

    public boolean isCrazyGood(Brand b) {
        return false;
    }
}

您创建了一个包含谓词和结果的列表,并使用stream、filter和findFirst遍历该列表并找到正确的结果。如果条件比这更简单,那么您就不需要谓词,并对其进行稍微不同的测试。

票数 3
EN

Stack Overflow用户

发布于 2018-10-11 09:23:23

首先,将isSuperCarisCrazyGood方法移到Brand中,而不是让它们接受Brand参数。类似地,您可以向Engine添加一个静态工厂方法来封装您试图编码的逻辑。这并不能完全避免“讨厌的if/else/switch语句”,但它的可读性可能要好得多。

例如:

代码语言:javascript
复制
public Car(Brand b) {
  this.engine = Engine.forBrand(b);
}

然后:

代码语言:javascript
复制
enum Engine {
  LEVEL1, LEVEL2, LEVEL3

  public static Engine forBrand(Brand b) {
    if (b.isSuperCar()) {
      return b.isCrazyGood() ? LEVEL1 : LEVEL2;
    }
    return LEVEL3;
  }
}

还要注意,您的isSuperCar方法可以简单地为:

代码语言:javascript
复制
return b.equals(Brand.FERRARI) || b.equals(Brand.PAGANI);

永远不需要编写if (...) return true; else return false;或任何类似的东西-只需直接在if语句中使用布尔表达式即可。

票数 3
EN

Stack Overflow用户

发布于 2018-10-17 16:10:03

如果Brand和Engine的映射是一对一的,您可以这样做:

代码语言:javascript
复制
enum Brand {
    MINI(Engine.LEVEL1),
    FERRARI(Engine.LEVEL2),
    PAGANI(Engine.LEVEL3);

    private final Engine engine;

    private Brand(Engine engine) {
        this.engine = engine;
    }

    public final Engine getEngine() {
        return engine;
    }
}

另一种选择:

代码语言:javascript
复制
enum Brand {
    MINI(false, false),
    FERRARI(true, true),
    PAGANI(false, true);

    private final boolean superCar;
    private final boolean crazyGood;

    private Brand(boolean superCar, boolean crazyGood) {
        this.superCar = superCar;
        this.crazyGood = crazyGood;
    }

    public final Engine getEngine() {
        if (superCar) {
            return (crazyGood) ? Engine.LEVEL1 : Engine.LEVEL2;
        }
        return Engine.LEVEL3;
    }
}

如果映射不是一对一的,并且您需要以某种方式基于某些参数动态计算引擎,则还可以使用以下方法:

代码语言:javascript
复制
enum Brand {
    MINI {
        @Override
        public Engine getEngine(boolean superCar, boolean crazyGood) {
            return (superCar && crazyGood) ? Engine.LEVEL1 : Engine.LEVEL2;
        }
    },
    FERRARI {
        @Override
        public Engine getEngine(boolean superCar, boolean crazyGood) {
            return superCar ? Engine.LEVEL1 : Engine.LEVEL3;
        }
    },
    PAGANI {
        @Override
        public Engine getEngine(boolean superCar, boolean crazyGood) {
            return Engine.LEVEL3;
        }
    };

    public abstract Engine getEngine(boolean superCar, boolean crazyGood);
}

或者像这样的东西,你有一些默认值,只有在特殊情况下才会覆盖:

代码语言:javascript
复制
enum Brand {
    MINI,
    FERRARI {
        @Override
        public Engine getEngine(boolean superCar, boolean crazyGood) {
            return superCar ? Engine.LEVEL1 : Engine.LEVEL3;
        }
    },
    PAGANI;

    public Engine getEngine(boolean superCar, boolean crazyGood) {
        return Engine.LEVEL3;
    }
}

使用枚举的可能性很大,实际上我更喜欢使用枚举而不是复杂的if/else或switch语句。当然,这取决于你到底想做什么,而且由于没有提供太多信息,我真的不能给出最好的答案。希望这能对你有所帮助。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52731165

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档