>
> I suppose that could be avoided by the use of private constructors and
> public static factory methods (different method names means there's no
> overloading, so no ambiguity in when signatures need to differ only by
> generic type argument). But we'd have to choose names for those static
> methods -- that's easy when you know that DeleteTopicsResult supports
> by-name and by-id variants, but we didn't know that originally, so it's
> likely those methods would end up with poor names. So it's not much of an
> improvement over public constructors, in my opinion.
>

Replying to myself... it's not so bad, because we'd use public constructors
initially and only provide factory methods when we needed to evolve the API
in a way such that overloaded constructors wouldn't work (e.g. due to
erasure ambiguity). Thus, the need to choose names for factory methods only
arises once we know how the API is evolving. For example we'd initially
have a single public constructor, such as
```
public CreateTopicsResult(Map<String, KafkaFuture<Void>> futures) { ... }
```
and then, when we wanted to change the parameter type argument, we'd switch
to factory methods:
```
@Deprecated // use withDescriptions
public CreateTopicsResult(Map<String, KafkaFuture<Void>> futures) { ... }
// Hide the constructor that has the disambiguated signature behind a
static factory method
private CreateTopicsResult(boolean disambiguator, Map<String,
KafkaFuture<TopicMetadataAndConfig>> futures) { ... }
public static CreateTopicsResult withDescriptions(Map<String,
KafkaFuture<TopicDescription>> futures) { ... }
```
Obviously the hidden constructor can have whatever signature we want (that
doesn't collide with the existing public one), so we could use multiple
parameters (as in the DeleteTopicsResult change) if there wasn't a way to
convert one parameter to another.

Reply via email to