Unlike some other languages. Java does not provide a keyword to mean "this class." So there is no easy way to ensure that register only a Container type ? super this class ? super this class . As a result, getting the string container.add(this); problematic for work.
A possible workaround is to create an Element generic, as described here . There are all kinds of problems with this approach (I personally donβt like it), including the problem solved by "getThis trick".
One of the problems is that it will not work with a chain of 3 classes / interfaces
Sub1Element extends ElementBasis implements Element
You can do this if you are doing ElementBasis generic as well as Element (all solutions to the related question include only chains of length 2). Here, I just replaced Collection with Container .
public interface Element<E extends Element<E>> { void register(Collection<? super E> container); } public class ElementBasis<E extends ElementBasis<E>> implements Element<E> { @Override public void register(Collection<? super E> collection) { collection.add((E) this);
This works, but since ElementBasis is a specific generic class with a self-referential constraint, you can only use it with wildcards.
This compiles cleanly:
ElementBasis<?> e = new ElementBasis<>(); List<ElementBasis<?>> list = new ArrayList<>(Arrays.<ElementBasis<?>>asList(e, e)); e.register(list); System.out.println(list);
However, wildcards are extremely confusing and seem unnecessary at first (although they are not).
Given all the problems with this approach, I would avoid this.
My preferred approach would be to get rid of all type parameters, stop trying to make register member of the Element and use the static method instead.
public static <E extends Element> void register(E e, Collection<? super E> collection) { collection.add(e); }
Paul boddington
source share