Instantly share code, notes, and snippets.

Embed
What would you like to do?
Anonymous Types with Java 10
package com.benjiweber.anontypes;
import java.util.*;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.UnaryOperator;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static java.util.stream.Collectors.*;
public class Example {
public static void main(String... args) {
var x = (Quacks & Waddles) Mixin::create;
x.quack(); // prints Quacking
x.waddle(); // prints Waddling
var y = (IsA<List<String>> & Mappable<String> & FlatMappable<String> & Joinable<String>)
() -> List.of("Anonyous", "Types");
System.out.println(y.join(",") + " - " + y.size()); // prints Anonymous,Types - 2
System.out.println(y.map(i -> i+i)); // prints [AnonyousAnonyous, TypesTypes]
System.out.println(y.flatMap(i -> List.of(i.split("")))); // prints [A, n, o, n, y, o, u, s, T, y, p, e, s]
}
interface Mixin {
void __noop__();
static void create() {}
}
interface Quacks extends Mixin {
default void quack() {
System.out.println("Quacking");
}
}
interface Waddles extends Mixin {
default void waddle() {
System.out.println("Waddling");
}
}
interface IsA<T> {
T delegate();
}
interface Mappable<T> extends ForwardingList<T> {
default <R> List<R> map(Function<? super T, ? extends R> mapper) {
return delegate().stream().map(mapper).collect(toList());
}
}
interface FlatMappable<T> extends ForwardingList<T> {
default <R> List<R> flatMap(Function<? super T, ? extends List<? extends R>> mapper) {
return delegate().stream().flatMap(i -> mapper.apply(i).stream()).collect(toList());
}
}
interface Joinable<T extends CharSequence> extends ForwardingList<T> {
default String join(CharSequence delimiter) {
return delegate().stream().collect(Collectors.joining(delimiter));
}
}
interface ForwardingList<T> extends List<T>, IsA<List<T>> {
List<T> delegate();
default int size() {
return delegate().size();
}
default boolean isEmpty() {
return delegate().isEmpty();
}
default boolean contains(Object o) {
return delegate().contains(o);
}
default Iterator<T> iterator() {
return delegate().iterator();
}
default Object[] toArray() {
return delegate().toArray();
}
default <T1> T1[] toArray(T1[] a) {
return delegate().toArray(a);
}
default boolean add(T t) {
return delegate().add(t);
}
default boolean remove(Object o) {
return delegate().remove(o);
}
default boolean containsAll(Collection<?> c) {
return delegate().containsAll(c);
}
default boolean addAll(Collection<? extends T> c) {
return delegate().addAll(c);
}
default boolean addAll(int index, Collection<? extends T> c) {
return delegate().addAll(index, c);
}
default boolean removeAll(Collection<?> c) {
return delegate().removeAll(c);
}
default boolean retainAll(Collection<?> c) {
return delegate().retainAll(c);
}
default void replaceAll(UnaryOperator<T> operator) {
delegate().replaceAll(operator);
}
default void sort(Comparator<? super T> c) {
delegate().sort(c);
}
default void clear() {
delegate().clear();
}
default T get(int index) {
return delegate().get(index);
}
default T set(int index, T element) {
return delegate().set(index, element);
}
default void add(int index, T element) {
delegate().add(index, element);
}
default T remove(int index) {
return delegate().remove(index);
}
default int indexOf(Object o) {
return delegate().indexOf(o);
}
default int lastIndexOf(Object o) {
return delegate().lastIndexOf(o);
}
default ListIterator<T> listIterator() {
return delegate().listIterator();
}
default ListIterator<T> listIterator(int index) {
return delegate().listIterator(index);
}
default List<T> subList(int fromIndex, int toIndex) {
return delegate().subList(fromIndex, toIndex);
}
default Spliterator<T> spliterator() {
return delegate().spliterator();
}
default boolean removeIf(Predicate<? super T> filter) {
return delegate().removeIf(filter);
}
default Stream<T> stream() {
return delegate().stream();
}
default Stream<T> parallelStream() {
return delegate().parallelStream();
}
default void forEach(Consumer<? super T> action) {
delegate().forEach(action);
}
}
}
@thinkbigthings

This comment has been minimized.

thinkbigthings commented Apr 21, 2018

It's cool that you can do something like this in Java 10. But I'm trying to understand how this is actually a mixin and how it is an improvement over e.g. creating a ForwardingList class and just adding the methods you want to that? Is there a way to add behavior to a class you don't have control over (like java List classes) without writing a forwarding method to re-implement the entire interface (as with ForwardingList here)?

@Dicee

This comment has been minimized.

Dicee commented Nov 7, 2018

You're using this feature very creatively but it feels pretty hacky. I wouldn't recommend anyone to use this in real code (but perhaps you wouldn't either!). It was interesting to see though, it wouldn't have crossed my mind to try this kind of things!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment