Typy ogólne

kowariancja tablic, typy ogólne, funkcje, konsumenci, itp.


dr inż. Aleksander Smywiński-Pohl

apohllo@o2.pl

http://apohllo.pl/dydaktyka/programowanie-obiektowe

Typ ogólny (generyczny, parametryzowany)

In [ ]:
class SingletonContainer<E> {
    private E element;
    
    public void put(E element){
        this.element = element;
    }
    
    public E get(){
        return element;
    }
}
In [ ]:
SingletonContainer<String> container = new SingletonContainer<>();
container.put("Ala");
String string = container.get();
System.out.println(string);
In [ ]:
SingletonContainer<Integer> container = new SingletonContainer<>();
container.put(1);
Integer integer = container.get();
System.out.println(integer);

Kowariancja tablic

In [1]:
class ArrayRuntimeError {
  public static void main(String[] args){
    String words[] = {"Ala", "ma", "kota"};
    Object[] objects = words;

    objects[0] = new Integer(1);
  }
}
org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
Script1.groovy: 3: expecting '}', found '=' @ line 3, column 20.
       String words[] = {"Ala", "ma", "kota"};
                      ^

1 error

	at org.codehaus.groovy.control.ErrorCollector.failIfErrors(ErrorCollector.java:310)
	at org.codehaus.groovy.control.ErrorCollector.addFatalError(ErrorCollector.java:150)
	at org.codehaus.groovy.control.ErrorCollector.addError(ErrorCollector.java:120)
	at org.codehaus.groovy.control.ErrorCollector.addError(ErrorCollector.java:132)
	at org.codehaus.groovy.control.SourceUnit.addError(SourceUnit.java:350)
	at org.codehaus.groovy.antlr.AntlrParserPlugin.transformCSTIntoAST(AntlrParserPlugin.java:144)
	at org.codehaus.groovy.antlr.AntlrParserPlugin.parseCST(AntlrParserPlugin.java:110)
	at org.codehaus.groovy.control.SourceUnit.parse(SourceUnit.java:234)
	at org.codehaus.groovy.control.CompilationUnit$1.call(CompilationUnit.java:168)
	at org.codehaus.groovy.control.CompilationUnit.applyToSourceUnits(CompilationUnit.java:943)
	at org.codehaus.groovy.control.CompilationUnit.doPhaseOperation(CompilationUnit.java:605)
	at org.codehaus.groovy.control.CompilationUnit.processPhaseOperations(CompilationUnit.java:581)
	at org.codehaus.groovy.control.CompilationUnit.compile(CompilationUnit.java:558)
	at groovy.lang.GroovyClassLoader.doParseClass(GroovyClassLoader.java:298)
	at groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:268)
	at groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:254)
	at groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:250)
	at org.scijava.plugins.scripting.groovy.GroovyScriptEngine.getScriptClass(GroovyScriptEngine.java:319)
	at org.scijava.plugins.scripting.groovy.GroovyScriptEngine.eval(GroovyScriptEngine.java:122)
	at javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:264)
	at org.scijava.script.ScriptModule.run(ScriptModule.java:159)
	at org.scijava.module.ModuleRunner.run(ModuleRunner.java:167)
	at org.scijava.jupyter.kernel.evaluator.Worker.run(Worker.java:109)
	at org.scijava.thread.DefaultThreadService$2.run(DefaultThreadService.java:220)
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at java.lang.Thread.run(Thread.java:745)
Out[1]:
No Outputs

Kowariancja list

In [ ]:
import java.util.*;

class ListCompilationError {
  public static void main(String[] args){
    List<String> words = Arrays.asList("Ala", "ma", "kota");
    List<Object> objects = words;

    objects.add(0,new Integer(1));
  }
}
In [ ]:
class ListGenericError {
  public static void main(String[] args){
    List<String> words = Arrays.asList("Ala", "ma", "kota");
    List<?> objects = words;

    String string = objects.get(0);
    objects.add(0,"Jola");
  }
}
In [ ]:
import java.util.*;

class ListGenerics {
  public static void main(String[] args){
    List<String> words = Arrays.asList("Ala", "ma", "kota");
    List<? extends String> objects = words;

    String string = objects.get(0);
    objects.add(0,"Jola");
  }
}

? extends vs ? super

In [ ]:
List<? extends Object> objects;

List<? super String> strings;

  • ? extends y => (czytaj) ? extends y
  • ? super y => (czytaj) ? isSuperOf y

Interfejs Consumer<T>

  • void accept(T t)
  • default Consumer<T> andThen(Consumer<? super T> after)
In [ ]:
Consumer<Number> numberConsumer;
Consumer<Integer> integerConsumer;
Consumer<Object> objectConsumer;
In [ ]:
numberConsumer.andThen(numberConsumer);
In [ ]:
numberConsumer.andThen(integerConsumer);
In [ ]:
numberConsumer.andThen(objectConsumer);
In [ ]:
integerConsumer.andThen(objectConsumer);
In [ ]:
import java.util.stream.*;
import java.util.function.*;

//       vvvvvvv
Consumer<Integer> print = x -> {      
    System.out.println("Jeden "); 
    System.out.println(1 + x); 
};

//       vvvvvv
Consumer<Object> printTwice = x -> {
    System.out.println("Dwa "); 
    System.out.println(x); 
    System.out.println(x); 
};

Consumer<Integer> combined = print.andThen(printTwice);

Arrays.asList(1,2,3,4,5,6,7,8,9,10).stream().forEach(combined);

Interfejs Function<T,R>

In [ ]:
default <V> Function<T,V> andThen(Function<? super R,? extends V> after)
R apply(T t)
default <V> Function<V,R> compose(Function<? super V,? extends T> before)
static <T> Function<T,T> identity()
In [ ]:
Function<Integer,Integer> intIntFunction = (x) -> x * 2;
Function<Number,String> numStrFunction = (x) -> x.toString();
Function<Object, Integer> objIntFunction = (x) -> x.toString().size();
In [ ]:
Function<Integer, Object> combined = intIntFunction.andThen(numStrFunction);
In [ ]:
T = Integer
R = Integer     // -> Number isSuperOf Integer 
V = Object      // -> String extends Object
In [ ]:
import java.util.stream.*;
import java.util.function.*;

Function<Integer,Integer> intIntFunction = (x) -> x * 2;
Function<Number,String> numStrFunction = (x) -> x.toString();

Function<Integer, Object> combined = intIntFunction.andThen(numStrFunction);

Arrays.asList(1,2,3,4,5,6,7,8,9,10).stream().map(combined).
    collect(Collectors.toList());

Wymazywanie typu

In [ ]:
class TypeErasure {
    public void consume(List<Integer> integers){
    }
    
    public void consume(List<String> strings){
    }
}
In [ ]:
|  Error:
|  name clash: consume(java.util.List<java.lang.String>) and 
|      consume(java.util.List<java.lang.Integer>) have the same erasure
|
|      public void consume(List<String> strings){
|      ^-----------------------------------------...

Pytania?