如何使用两个布尔变量确定不同的行为?

3

我有2个boolean变量,例如:

boolean isWhite;
boolean isTall;

所以,我想为4种可能的情况({(isWhite, isTall), (!isWhite, isTall), (isWhite, !isTall), (!isWhite, !isTall)})确定不同的行为。

1) 有没有比每次使用if/else更优雅和实用的方法?

if(isWhite) {
    if(isTall) {
        // Case 1
    }
    else {
        // Case 2
}
else {
    if(isTall) {
        // Case 3
    }
    else {
        // Case 4
}

2) 如果这样做会有任何不同吗?

if (isWhite && isTall)
    // Case 1
if (isWhite && !isTall)
    // Case 2
if (!isWhite && isTall)
    // Case 3
if (!isWhite && !isTall)
    // Case 4

2
提示:考虑 if(isWhite && isTall)。如果这个测试是 false,那么你就知道要么 1) isWhite == false,2) isTall == false 或者 3) 两者都是 false。所以你只需要测试 !isWhite!isTall!isWhite && !isTall。进一步的推断也是可能的,但可能会增加复杂性。 - Boris the Spider
如果行为完全不同,我更喜欢#2,因为更深的缩进似乎更难阅读。您还可以在Scala中搜索案例类/模式匹配,以查看另一种可用选项。 - Ivan
2
如果你打算这样做,最好使用“else-if”。 - Pavneet_Singh
6个回答

6

你的第二种方案更易读。但是你应该使用if-else而不是只用if语句。考虑如果第一个条件已经为真。其他三个if语句仍将被计算。如果你使用if-else语句并且第一个条件为真,其他三个语句将被跳过。

if (isWhite && isTall) {//case1}
else if (isWhite && !isTall) {//case2}
else if (!isWhite && isTall) {//case3}
else {//case4}

最后的 !isWhite 是多余的。 - Peter Lawrey

4

如果您可以使用enum,我更倾向于使用第一种if/else的排列方式。假设您的布尔值为ab

enum Combination { 
   A_B, NA_B, A_NB, NA_NB;
}

其中NA_NB表示不是A,也不是B。

switch(comb) {
   case A_B:
         //
         break;
   // more cases
   case NA_NB:
         //
         break;
}

当您拥有更多的布尔值并且可以进行不可能的组合时,这种方法会更好地扩展。

这适用于完全删除if/else块。

enum Combination implements Actionable { 
   A_B {
      public void action(Arg arg) {
          // something
      }
  },
  NA_B {
      public void action(Arg arg) {
          // something
      }
  },
  A_NB {
      public void action(Arg arg) {
          // something
      }
  },
  NA_NB {
      public void action(Arg arg) {
          // something
      }
  };
}

现在,你可以直接调用一个函数,而不需要使用if/else或者switch语句。
actionable.action(something);

你也可以轻松添加各种组合,甚至可以添加原始库中未包含的自定义 Actionable


我非常喜欢Java,但它最烦人的一面之一就是你想避免编写8行if/else语句,结果你最终编写了30行样板代码。 - Eric Duminil
另外,你如何初始化你的组合?它必须来自某个地方,所以你可能仍然需要一些布尔逻辑来决定是否使用 NA_NBA_B - Eric Duminil
1
@EricDuminil 这取决于你的情况有多复杂。当你开始使用一些标志时,你可能会发现想要一些选项来重构它以添加一些结构。 - Peter Lawrey

2
另一种选择是将它们转换为 int(即 0 和 1),并使用 switch 语句来识别所有情况,例如:
public static void main(String[] args) throws Exception{
    boolean white = true, tall = false;

    StringBuilder result = new StringBuilder();
    result.append(white ? 1 : 0);
    result.append(tall ? 1 : 0);


    switch(result.toString()){
        case "00":
            //do something
            break;

        case "01":
            //do something
            break;

        case "10":
            //do something
            break;

        case "11":
            //do something
            break;
    }

}

1
或者你可以使用 switch((white?10:0)+(tail?1:0)),避免创建任何对象。 - Peter Lawrey

0

这样怎么样?与之前的答案类似,但我使用else if来缩短代码,在处理布尔值不相同时的两种情况时。

if(isWhite && isTall){/**case 1*/}
else if(isWhite){/**case 2*/}        // only need one boolean
else if(isTall){/**case 3*/}         // on each of these lines
else{/**case 4*/}

节省一些打字的工作 :)


0
另一种可能性是直接从布尔值计算您的caseNumber:
int caseNumber = 1 + (isWhite ? 0 : 2) + (isTall ? 0 : 1);

这是一个例子:

import java.util.*;
import java.lang.*;
import java.io.*;

class Ideone
{
    public static void main (String[] args) throws java.lang.Exception
    {
        System.out.println(getCaseNumber(true,true));
        System.out.println(getCaseNumber(true,false));
        System.out.println(getCaseNumber(false,true));
        System.out.println(getCaseNumber(false,false));
        switch(getCaseNumber(true,false)){
            case 1:
                System.out.println("Case 1!");
                break;
            case 2:
                System.out.println("Case 2!");
                break;
            case 3:
                System.out.println("Case 3!");
                break;
            case 4:
                System.out.println("Case 4!");
                break;              
        }
    }

    private static int getCaseNumber(boolean bool1, boolean bool2)
    {
        return 1 + (bool1 ? 0 : 2) + (bool2 ? 0 : 1);
    }
}

它输出:

1
2
3
4
Case 2!

遍历所有可能性更容易,对于n个布尔值来说,它的可扩展性更好,并且在使用switch语句时更容易。

1 +只是为了匹配您的情况定义,在其中(true,true)Case 1

如果您想要caseNumber02 ** n-1之间,则可以将其删除。


1
你能澄清 1 + 的目的吗? - Peter Lawrey

0

这是一个经常出现的模式,其中属性根据某些业务逻辑(基于现实世界)定义不同的情况。

这种控制流程很难进行测试、验证和跟踪错误。

最好的方法是将其更多或更少地变成一个声明性列表。也许远程类似于:

{ false, false, (isWhite, isTall) -> { ... } },
{ false, true, (isWhite, isTall) -> { ... } },
{ true, false, (isWhite, isTall) -> { ... } },
{ true, true, (isWhite, isTall) -> { ... } },

(使用枚举更易读。)

通过这种方式,您可以创建插件(具有用例的XML),记录更好(处理程序类名)。特别是这个声明性列表可以作为业务逻辑的规范,可供客户阅读。因此,如果选择的处理程序被赋予字符串ID +版本,则会出现在某种形式的用户面前。例如,在PDF中的表单版本。

这意味着代码设计的改变。但是,例如在许多类似报告的情况下,这对我有所帮助。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接