Парадигмы программирования
Полиморфизм и Generics
1 + 1
1.0 + 1.0
1.0 + 1
String.format("%d", 10);
String.format("Hello, %s!", "world");
void draw(Shape shape) { if (shape instanceof Rect) … if (shape instanceof Circle) … }
void drawWithColor(Shape shape, Color color) { shape.setColor(color); shape.draw(); }
template <typename T> bool contains(T x, T* a, int size) { for (int i = 0; i < size; i++) { if (x == a[i]) { return true; } } return false; }
<T> boolean contains(T item, T[] array) { for (T value : array) { if (item.equals(value)) { return true; } } return false; }
interface Stack<E> { void push(E element); E pop(); E peek(); … }
class ArrayStack<E> implements Stack<E> { ... }
Stack stack = new ArrayStack(); stack.push(1); Integer i = (Integer) stack.pop();
Stack<Integer> stack = new ArrayStack<Integer>(); stack.push(1); Integer i = stack.pop();
Stack<Integer> stack = new ArrayStack<>();
class ArrayStack<E> implements Stack<E> { private E[] elements; private int size; public ArrayStack() { elements = (E[]) new Object[10]; } public E peek() { return elements[size - 1]; } …
Stack<Integer> si = new ArrayStack<>();
Stack<Object> so = si;
so.push("hello"); // ClassCastException Integer li = si.peek();
void dump(Stack<Object> stack) { while (!stack.isEmpty()) { Object o = stack.pop(); System.out.println(o); } }
dump(new ArrayStack<Object>(…));
dump(new ArrayStack<Integer>(…));
void dump(Stack<?> stack) { while (!stack.isEmpty()) { Object o = stack.pop(); System.out.println(o); } }
dump(new ArrayStack<Object>(…));
dump(new ArrayStack<Integer>(…));
void draw(Stack<Shape> stack) { while (!stack.isEmpty()) { Shape shape = stack.pop(); shape.draw(); } }
draw(new ArrayStack<Shape>(…));
draw(new ArrayStack<Circle>(…));
void draw(Stack<? extends Shape> stack) { while (!stack.isEmpty()) { Shape shape = stack.pop(); shape.draw(); } }
draw(new ArrayStack<Shape>(…));
draw(new ArrayStack<Circle>(…));
void pushAll(Object[] a, Stack<Object> stack) { for (int i = 0; i < a.length; i++) { stack.push(a[i]); } }
pushAll(new Object[10], new ArrayStack<Object>());
pushAll(new String[10], new ArrayStack<Object>());
pushAll(new String[10], new ArrayStack<String>());
pushAll(new Object[10], new ArrayStack<String>());
<T> void pushAll(T[] a, Stack<T> c) { for (int i = 0; i < a.length; i++) { stack.push(a[i]); } }
pushAll(new Object[10], new ArrayStack<Object>());
pushAll(new String[10], new ArrayStack<Object>());
pushAll(new String[10], new ArrayStack<String>());
pushAll(new Object[10], new ArrayStack<String>());
<T> void moveAll(Stack<T> s1, Stack<T> s2) { while (!s1.isEmpty()) { T o = s1.pop(); s2.push(o); } }
moveAll(new AS<Integer>(…), new AS<Integer>());
moveAll(new AS<Integer>(…), new AS<Object>());
moveAll(new AS<Object>(…), new AS<Integer>());
<T, S extends T> void moveAll(Stack<S> s1, Stack<T> s2) { while (!s1.isEmpty()) { s2.push(s1.pop()); } }
moveAll(new AS<Integer>(…), new AS<Integer>());
moveAll(new AS<Integer>(…), new AS<Object>());
moveAll(new AS<Object>(…), new AS<Integer>());
<T> void moveAll(Stack<? extends T> s1, Stack<T> s2) { while (!s1.isEmpty()) { s2.push(s1.pop()); } }
moveAll(new AS<Integer>(…), new AS<Integer>());
moveAll(new AS<Integer>(…), new AS<Object>());
moveAll(new AS<Object>(…), new AS<Integer>());
<T extends Comparable<T>> T max(Stack<T> stack) { ... }
Integer i = max(new AS<Integer>(…));
class Test implements Comparable<Object> {…}
Test t = max(new AS<Test>(…));
<T extends Comparable<? super T>> max(Stack<T> stack) { … }
Integer I = max(new AS<Integer>(…));
class Test implements Comparable<Object> {…}
Test t = max(new AS<Test>(…));
/** Duplicates top element of the stack. */ // Часть интерфейса void dup(Stack<?> stack) { // Как реализовать? }
void dup(Stack<?> stack) { stack.push(stack.peek()); }
// Часть интерфейса void dup(Stack<?> stack) { dupImpl(stack); } // Настоящая реализация private <T> void dupImpl(Stack<T> stack) { stack.push(stack.peek()); }
interface Reader<T> { T read(); }
Reader<Object> objR = ... Reader<String> strR = objR; String data = strR.read();
Reader<String> strR = ... Reader<Object> objR = strR; Object data = objR.read();
interface Writer<T> { write(T value); }
Writer<Object> objW = ... Writer<String> strW = objW; strW.write(new String());
Writer<String> strW = ... Writer<Object> objW = strW; objW.write(new Object());
Stack<T>
Stack<Object> os = ... Stack<String> ss = os; ss.push(new Object()); String s = ss.pop();
Stack<String> ss = ... Stack<Object> os = ss; os.push(new Object()); Object os = os.pop();
Reader<String> strR = ... Reader<? extends Object> objR = strR; Object data = objR.read();
Writer<Object> objW = ... Writer<? super String> strW = objW; strW.write(new String());
interface Function<T, R> { R apply(T argument); }
Function<T1, R1> f1; Function<T2, R2> f2 = f1;
static <T, R> Function<T, R> cast( Function<? super T, ? extends R> f ) { return new Function<T, R>() { public R apply(T argument) { return f.apply(argument); } }; }
List<String> list = new ArrayList<>(…); String max = list.get(0); for (int i = 1; i < list.size(); i++) { String next = list.get(i); if (next.compareTo(max) > 0) { max = next; } }
List list = new ArrayList(…); String max = (String) list.get(0); for (int i = 1; i < list.size(); i++) { String next = (String) list.get(i); if (next.compareTo(max) > 0) { max = next; } }
Stack<String> ss = new AS<String>(); Stack<Integer> si = new AS<Integer>(); ss.getClass() == si.getClass() // True
ss instanceof AS // True
ss instanceof AS<String> // Запрещено
Stack s = new ArrayStack<String>();
Stack<String> s = (Stack<String>) new ArrayStack();
Stack<String> s1 = new ArrayStack();
@SuppressWarnings("unchecked") Stack<String> s1 = new ArrayStack();
Stack<T> s;
T[] elements; // Object[]
new T[10];
new ArrayStack<Stack<Integer>>();
Stack<?>[] stacks = new Stack<?>[10];
new Stack<Integer>[10];
Function<Object, Integer> foi = …;
Function<String, Number> fso = Function.cast(foi);
Function<String, Number> fso = Function.<String, Number>cast(foi);
Stack<Number> ns = stack.map(Function.cast(foi));
Stack<Number> ns = stack.<Number>map( Function.<String, Number>cast(foi));
Stack<Number> ns = stack.map( Function.<String, Number>cast(foi));
interface Reader<T, E extends Exception> { T next() throws E; boolean hasNext() throws E; }
<T, E extends Exception> List<T> readAll(Reader<T, E> reader) throws E { final List<T> result = new ArrayList<>(); while (reader.hasNext()) { result.add(reader.next()); } return result; }
class StrangeExample< I, C extends Collection<I> & Comparable<? super C> > { C coll; void add(I item) { coll.add(item); } int compare(C other) { return coll.compareTo(other); } }
class ListBuilder<T> { private final List<T> list = new ArrayList<>(); ListBuilder<T> add(T item) { list.add(item); return this; } List<T> build() { return list; } }
List<String> hello = new ListBuilder<String>() .add("hello") .add("world") .build();
class AllBuilder<T> extends ListBuilder<T> { AllBuilder<T> addAll(Collection<T> items) { for (T item : items) { add(item); } return this; } }
List<String> hello = new AllBuilder<String>() .add("hello") .addAll(List.of("world")) .build();
class ListBuilder<B extends ListBuilder<B, T>, T> { B add(T item) { /* ... */ return self(); } B self() { return (B) this; }
class AllBuilder<B extends AllBuilder<B, T>, T> extends ListBuilder<B, T> { B addAll(List<T> item) { /* ... */ return self(); }
class ConcreteBuilder<T> extends AllBuilder<ConcreteBuilder<T>, T> {