如何在java中扩展下面的API函数而不导致歧义

How to extend the following API function in java and not lead to ambiguous

我有一些现有的重载 API:

1). foo(a, b) { return foo(a, b, null); }
2). foo(a, b, c) {return foo(a,b,c,null);}
3). foo(a, b, c, d) { implement of the function...; }

其中a,b,c是一些数据结构,其值也可以为null。 现在我需要用一个标志来扩展 APIs。即

4). foo(a, b, Boolean flag)
5). foo(a, b, c, Boolean flag)
6). foo(a, b, c, d, Boolean flag)

其中布尔值可以是null/false/true; 为了兼容性,现有的 API 应该仍然存在。

问题是:调用 foo(a, b, null) 时,2) 和 4) 不明确。 3) 和 5).

也一样

我的问题:一般来说,我们应该如何扩展新 API?

如果你使用Java8,你应该使用OptionalBoolean而不是Boolean。它不如它的同伴 Optional<>OptionalIntOptionalDouble 等,但在这种情况下,它可能是一个真正的好处。

由于提到的 OptionalBoolean 确实来自 com.sun.javafx.scene.control.behavior.OptionalBoolean,因此可能有更好的选择。

我个人尽量避免在有更好选择的地方使用 null

而不是

class Foo {
    Bar s; // whatever Bar is...
    Foo() {
        Foo(null)
    }

    Foo(Bar s) {
        this.s = s;
    }

    public void doStuff() {
        if (s != null) {
            bar.frobnicate();
        }
    }
}

最好有

class Foo {
    Bar s; // whatever Bar is...
    Foo() {
        Foo(Bar.EMPTY_VALUE)
    }

    Foo(Bar s) {
        this.s = s;
    }

    public void doStuff() {
        bar.frobnicate();
    }
}

Bar 有一个

public final static EMPTY_VALUE = new Bar() {
    // redefine it so that frobnicate() just does nothing.
    // This way, EMPTY_VALUE can be used wherever appropriate
}

这叫做Null Object pattern。虽然它没有直接解决您的问题,但它通过在各处使用 null 解决了您的歧义。


解决它们的另一种方法是让每个构造函数直接调用 "main constructor"。

这样你就可以

foo(a, b) { return foo(a, b, null, null); }
foo(a, c) { return foo(a, null, c, null); }
foo(a, b, c) {return foo(a,b,c,null);}
foo(a, b, d) {return foo(a,b,null, c);}
foo(a, b, c, d) { implement of the function...; }

读起来还不如更清楚

a) 您可以为新方法指定一个不同的名称。 fooWithFlag

b) 你不能允许 null(大概它和以前没有标志的方法做同样的事情),而是使用原语 boolean 而不是

c) 您可以创建一个子接口 ServiceWithFlagsServiceV2 并将新方法仅放在该接口上。新代码可以通过新接口来使用它,旧代码仍然使用旧接口,不会看到方法。

d) 这只是一个编译时错误。这不会破坏已经编译的代码。所以你实际上可以继续并添加你的新方法。编译器会捕获任何歧义,并在开发过程中轻松修复。

您可以使用枚举作为具有三种状态的标志,而不仅仅是一个布尔标志。

回答我的问题:

我觉得这样调用会避免歧义: 对于 2) foo(a, b, c) 和 4) foo(a, b, Boolean) 如果 我这样调用:foo(x, y, Boolean(null)) 而不是 foo(x, y, null), 这样就避免了歧义。