1

I have some existing overloading 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...; }

Where a, b, c are some data structure the value of which can be null as well. now I need to extend the APIs with a flag. i.e.

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

Where Boolean can be null/false/true; the existing APIs should exist still for compatability.

The problem is: 2) and 4) are ambiguous when foo(a, b, null) is called. same thing for 3) and 5).

My question: How in general we should extent the new API?

user389955
  • 9,605
  • 14
  • 56
  • 98

4 Answers4

1

If you use Java 8, you should use OptionalBoolean instead of Boolean. It is not as good as its companions Optional<>, OptionalInt, OptionalDouble etc., but in this case, it might be a real benefit.

As the mentionned OptionalBoolean is indeed from com.sun.javafx.scene.control.behavior.OptionalBoolean, there might be a better alternative.

I personally try to refrain from using null where there are better options.

Instead of

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

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

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

it might be better to have

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

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

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

with Bar having a

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

This is called the Null Object pattern. While it doesn't directly address your problem, it resolves the ambiguities you have by using null here and there.


Another way to resolve them could be to have every constructor call the "main constructor" directly.

This way you could have

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...; }

It might as well be clearer to read.

glglgl
  • 89,107
  • 13
  • 149
  • 217
  • And this will resolve the ambiguity for `null` ? Isn't `null` technically also a valid (though useless) value for OptionalBoolean (so that you would get the same compile error)? – Thilo Feb 26 '15 at 07:04
  • Is there an OptionalBoolean? http://stackoverflow.com/questions/23922134/is-java-8-missing-an-optionalboolean – Thilo Feb 26 '15 at 07:07
  • it seem mine is lower than java8.Thx – user389955 Feb 26 '15 at 07:29
  • @Thilo There is indeed one - but, as I just managed to see, has the full path `com.sun.javafx.scene.control.behavior.OptionalBoolean`, so not one of the standard ones... – glglgl Feb 26 '15 at 07:56
1

a) You could give the new methods a different name. fooWithFlag

b) You could not allow null (presumably it does the same thing as the previous methods without the flag), and use a primitive boolean instead

c) You could create a sub-interface ServiceWithFlags or ServiceV2 and put the new methods only on that. New code can make use of it by using the new interface, old code still uses the old interface and won't see the methods.

d) This is only a compile-time error. This will not break things for already compiled code. So you could actually go ahead and add your new methods. Any ambiguity will be caught by the compiler and is easily fixed during development.

Thilo
  • 257,207
  • 101
  • 511
  • 656
  • really? then they are different APIs. what I want to design is: when new API feature is enabled, if user call foo(a,b,c) or foo(a,b,c, false), foo(a, b, c, false) is called, if user call foo(a,b,c, true), then foo(a,b,c, true) is called; when new API feature is disabled, if user call foo(a,b,c), internally foo(a, b, c, false) is called, if user call foo(a,b,c, true/false), they get API not supported. – user389955 Feb 26 '15 at 07:11
  • That seems to be up to the implementation of these methods. Should not affect how the API looks. – Thilo Feb 26 '15 at 07:14
  • so for your approach 1 or 2, I have to copy and paste all existing API to new API and there are no way for them to share the same code, correct? – user389955 Feb 26 '15 at 07:48
  • Of course they can share code. You can have `foo(a,b,c)` implemented as `return foo(a,b,c,false)`. – Thilo Feb 26 '15 at 11:12
0

Instead of just a boolean flag you could use an Enum as Flag with the three states.

fsch
  • 201
  • 1
  • 5
  • 17
0

Answer my question:

I think calling in this way will avoid ambiguous: for 2) foo(a, b, c) and 4) foo(a, b, Boolean) if I call in this way: foo(x, y, Boolean(null)) in stead of foo(x, y, null), then ambiguous will be avoided.

user389955
  • 9,605
  • 14
  • 56
  • 98