Введение в программирование
Полиморфизм и 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> {