Skip to content

Exploit generic variance to ensure typing works as best as possible #1533

@victornoel

Description

@victornoel

Lots of constructors and methods in cactoos take Iterable, Scalar, Func and so on.

Because of the way typing works in Java, it can sometimes be challenging to have code compile even though it is conceptually sound. For example if we have a method or a constructor like this:

void method(Iterable<Scalar<Number>> numbers) { ... }

Then the following happens;

List<LengthOf> list = new ListOf<>(new LengthOf("some text"));
method(list); // does not compile because the types does not exactly match
method(new ListOf<>(new LengthOf("some text")); // compile because the correct type is inferred

In more complex situation, type inference does not even succeed.

The typical solution is to ensure that when using generics as parameters, then variance should be properly defined. The basic rules is that if a generic type is used in outputs of the interface methods, it should be relaxed w.r.t to its subclasses and if it is an input, then w.r.t. its parent classes. For, the above example, this gives us:

void method(Iterable<? extends Scalar<? extends Number>> numbers) { ... }

Of course this only makes sense if the type parameter is either a non-final class or a generic type from the enclosing class or method.

So every where Iterable, Iterator, Scalar, Callable, Supplier, Func, Proc, BiFunc, BiProc are used we need:

  • Iterable<? extends X>
  • Iterator<? extends X>
  • Scalar<? extends X>
  • Supplier<? extends X>
  • Callable<? extends X>
  • Func<? super X, ? extends Y>
  • Proc<? super X>
  • BiFunc<? super X1, ? super X2, ? extends Y>
  • BiProc<? super X1, ? extends X2>

Let's start by package bytes and go on through all of them one by one in alphabetical order by introducing todos once a package or part of it is done. Let's also add some more tests when it makes sense to validate it compiles correctly.

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions