使用条件运算符来选择哪个对象调用特定方法?

发布于 2024-08-19 06:28:00 字数 641 浏览 8 评论 0原文

我有两个集合,以及根据是否满足某些条件添加到其中一个或另一个集合的项目。

有点不经意间,我偶然发现这样一个事实,即编写

(test(foo) ? cOne : cTheOther).add(foo);

而不是

if (test(foo)) {
 cOne.add(foo);
} else {
 cTheOther.add(foo);
}

合法的虽然第一个让我感觉很聪明(总是一个优点),但我不确定长期的可读性,可维护性等。我看到的基本优点是如果我知道我总是会做同样的事情,那么它就成为更改方法的一个位置(而不是两个,或者如果我正在实现通过条件运算符的 switch 语句)。当情况并非如此时,主要缺点就会出现(即,我需要向某些情况添加方法调用,而不是其他情况)。

您认为这两种方法(或其他解决方案)有何优缺点?

如果您认为使用条件运算符来设置调用方法的对象的特定实例不正确选择,是否存在合理的情况?

I have two collections, and items that are added to one or the other of those collections based on whether some criteria is met.

Somewhat inadvertantly, I stumbled on the fact that it is legal to write

(test(foo) ? cOne : cTheOther).add(foo);

instead of

if (test(foo)) {
 cOne.add(foo);
} else {
 cTheOther.add(foo);
}

While the first makes me feel clever (always a plus), I'm not sure about longer term readability, maintainability, etc. The basic advantage I see is that if I know I'm always going to be doing the same thing, it becomes one location to change a method (instead of two, or perhaps many if I'm implementing a switch statement via conditional operators). The main disadvantage occurs when that becomes not the case (i.e., I need add a method call to some cases and not others).

What pros and cons of the two methods (or other solutions) do you see?

If you don't think this particular instance of using the conditional operator to set which object to call a method with is the right choice, are there cases where it is reasonable?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

暮光沉寂 2024-08-26 06:28:00

换句话说,一个更简单的代码片段是将

SomeClass component = test(foo) ? cOne : cTheOther;
component.add(foo);

分配与使用分开。

A simpler code snippet would be

SomeClass component = test(foo) ? cOne : cTheOther;
component.add(foo);

In other words, separate the assignment from the use of it.

七度光 2024-08-26 06:28:00

尽管这个例子很聪明,但可读性和可维护性始终是最聪明的想法。

关于条件运算符,您最多只能有两个值,如果您的条件超出该最大值,则可能会变得不可读。条件运算符不是处理不同值的标准方法。

As clever as the example is, readability and maintainability is always the smartest idea.

In regards to the conditional operator, you should only have a maximum of two values, if your condition goes beyond that maximum it may become unreadable. Conditional operators are not a standard way of dealing with different values.

深海夜未眠 2024-08-26 06:28:00

我反对在 if 语句的每个分支中长期调用函数,因为并不总是清楚要调用的函数是否是偶然的相同,并且如果您需要更改被调用的函数,则需要更改两个地方函数(好吧,“添加”是一个简单的例子)。出于这个原因,我通常会将正确的对象分配给变量(通常在 if 语句中,因为通常还会发生一些其他事情),但将所有常见代码拉到条件之外。

I am against the long-hand calling of the function in each branch of the if statement, because it's not always clear whether it's happenstance that the function to be called is the same and it's two places to change if you ever need to change the called function (okay, 'add' is an easy case). For that reason, I would normally assign the correct object to a variable (usually in an if statement, as there's usually a little other stuff going on too) but pull all common code outside the conditional.

自在安然 2024-08-26 06:28:00

我的首选方法是:

final boolean    result;
final Collection c;

result = test(foo);

if(result)
{
    c = cOne;;
} 
else 
{
    c = cOther;;
}

c.add(foo);

首先,我不喜欢进行调用并且不将值分配给临时变量(test(foo) 调用),原因有两个:

  1. 它更容易调试(System.out.println,甚至调试器) - 如果该方法有副作用,那么只需在调试器中查看它就会再次调用它 - 从而导致副作用)。
  2. 即使没有副作用,它也会阻止您多次调用它,这会使代码更加高效。编译器/热点应该处理删除不需要的临时变量的问题。

其次,我不喜欢代码,如果你模糊你的眼睛,它看起来是一样的。如果你“模糊”你的眼睛,让 cOne.add(foo) 和 cOther.add(foo) “看起来”是一样的。例如,如果您将其更改为列表并使用 add(int, E) 而不是 add(E),那么您只有一个地方可以更改代码,这意味着犯错误的更改会更少(例如 cOne.add (1, foo) 和 cOther.add(2, foo) 当它们都应该是 add(1, foo)) 时。

编辑(根据评论)

有几种选择,这取决于您如何布置代码。我可能会选择类似:

private Collection<Whatever> chooseCollection(final Whatever             foo,
                                              final Collection<Whatever> a,
                                              final Collection<Whatever> b)
{
    final boolean              result;
    final Collection<Whatever> c;

    result = test(foo);

    // could use a conditional - I just hate using them
    if(result)
    {
        c = a;
    }
    else
    {
        c = b;
    }

    return (c);
}

然后使用类似:

for(......)
{
    final Collection<Whatever> c;
    final Whatever             foo;

    foo = ...;
    c = chooseCollection(foo, cOne, cOther);
    c.add(foo;
}

本质上,如果有意义的话(通常是这样),我会为 { } 块内的任何内容创建一个方法。我喜欢有很多小方法。

My preferred way is:

final boolean    result;
final Collection c;

result = test(foo);

if(result)
{
    c = cOne;;
} 
else 
{
    c = cOther;;
}

c.add(foo);

First off I don't like making calls and not assigning the value to temp variable (the test(foo) call) for two reasons:

  1. it is easier to debug (System.out.println, or even the debugger - if the method has side effects then just looking at it in a debugger will call it again - thus causing the side effects).
  2. even if there are no side effects, it discourages you from calling it more than once, which make the code more efficient. The compiler/hotspot should deal with the removal of the unneeded temp variable.

Secondly I don't like having code where, if you blur your eyes, it looks the same. Having cOne.add(foo) and cOther.add(foo) "look" the same if you "blur" your eyes. If, for example, you were changing it to a List and using add(int, E) instead of add(E) then you only have one place to change the code, which means less change of making a mistake (like cOne.add(1, foo) and cOther.add(2, foo) when they should both be add(1, foo)).

EDIT (based on the comment)

There are a couple of choices, it depends on how you have the code layed out. I would probably go with something like:

private Collection<Whatever> chooseCollection(final Whatever             foo,
                                              final Collection<Whatever> a,
                                              final Collection<Whatever> b)
{
    final boolean              result;
    final Collection<Whatever> c;

    result = test(foo);

    // could use a conditional - I just hate using them
    if(result)
    {
        c = a;
    }
    else
    {
        c = b;
    }

    return (c);
}

and then have something like:

for(......)
{
    final Collection<Whatever> c;
    final Whatever             foo;

    foo = ...;
    c = chooseCollection(foo, cOne, cOther);
    c.add(foo;
}

Essentially I make a method for anything inside of a { } block if it makes sense (and usually it does). I like to have a lot of small methods.

桜花祭 2024-08-26 06:28:00

使用条件运算符的一个潜在问题是参数开始变得更加复杂。例如,如果以下行抛出 NullPointerException:

String aString = obj1.getValue() == null ? obj2.getString() : obj1.getValue().getString();

三个取消引用中的哪一个导致了 NPE? obj1obj2obj1.getValue() 有时可能可以通过前面代码中的推断来解决这个问题,但并非总是如此……

也就是说,比较以下两段代码:

final String aString = obj1 == null ? "default" : obj1.getString();

vs

final String aString;
if (obj1 == null) {
  aString = "default";
} else {
  aString = obj1.getString();
}

大多数人会认为条件更容易阅读,而且肯定更简洁。

现在,既然这样,我可以使用条件来调用方法吗?不,它增加了很多视觉上的复杂性,而且必须记住,调试的难度是编写代码的两倍。这意味着代码越简单,您或其他人在六个月内理解它就越容易。我非常乐意在接受的答案中使用两行版本。

One potential problem with using conditional operators is when the arguments start to become more complex. For example, if the following line throws a NullPointerException:

String aString = obj1.getValue() == null ? obj2.getString() : obj1.getValue().getString();

which of the the three dereferences is causing the NPE? obj1, obj2 or obj1.getValue() Sometimes it might be possible through inference in the preceding code to work it out, but not always…

That said, compare the following two pieces of code:

final String aString = obj1 == null ? "default" : obj1.getString();

vs

final String aString;
if (obj1 == null) {
  aString = "default";
} else {
  aString = obj1.getString();
}

Most people would argue that the conditional is simpler to read, and it is certainly more concise.

Now, with that out of the way, would I use a conditional to call a method? No, it adds a lot of visual complexity, and one has to remember, that debugging is twice as hard as writing code. That means that the simpler the code is, the simpler it is for you, or someone else, to understand it in six months time. I would be more than happy to use the two line version in the accepted answer.

阿楠 2024-08-26 06:28:00

用于此目的的条件运算符相当罕见,因此眼睛并不会真正寻找它。

我喜欢我的 Java 代码看起来一致,这样我和未来的维护人员就可以轻松发现分支、过于复杂等问题。由于我在其他地方使用 if,因此我通常可以吸收使用条件来执行此操作的成本。

如果我使用一种通过表达式执行大量“技巧”的语言,例如 Python,那就是另一回事了。

Conditional operators used for this purpose is fairly rare so the eye isn't really looking for it.

I like my Java code to look consistent, so that me and future maintainers can easily spot things like branches, too much complexity, etc. Since I use ifs elsewhere, I can usually absorb the cost of doing it over using a conditional.

If I'm using a language where I'm doing lots of "tricks" via expressions, such as Python, that's a different story.

写下不归期 2024-08-26 06:28:00

恕我直言,“完整”的长版本更具可读性,并且从长远来看肯定更适合维护。

IMHO the "full", long version is a little bit more readable and definitely better for maintenance in the long term.

π浅易 2024-08-26 06:28:00

我更喜欢第一个(或马特的中间解决方案)。它只是更短。如果条件运算符在您的项目中使用得相当频繁,人们就会习惯它并且“可读性”会增加。

或者换句话说:如果你习惯了 Perl,你就可以轻松阅读它。

I would prefer the first one (Or the intermediate solution by matt). It is just shorter. If the conditional operator is used rather often in your project, people get used to it and "readability" increases.

Or in other words: if you are used to Perl, you can easily read it.

柏拉图鍀咏恒 2024-08-26 06:28:00

添加到 matt b 所说的内容中,当您决定使用条件运算符时,您可以更进一步并使用这种格式:

SomeClass component = test(foo) 
   ? cOne 
   : cTheOther;
component.add(foo);

它使代码更具 if-else 感觉,并且更易于阅读。

Adding to what matt b said, you could go one step further and use this format, when you decide to use the conditional operator:

SomeClass component = test(foo) 
   ? cOne 
   : cTheOther;
component.add(foo);

It gives the code more of an if-else feel, and makes it easier to read.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文