JetBrains Academy: Wildcards - Kamil-Jankowski/Learning-JAVA GitHub Wiki

JetBrains Academy: Wildcards

Packing backeries:

You are working in a Pie company. The business going well and bakeries are selling abroad. Sometimes due to custom rules and trade regulations, it is necessary to package bakeries into the box with a more basic name like Bakery or Food. Full class hierarchy follows:

class Food {}
 
class Bakery extends Food {}
 
class Cake extends Bakery {}
 
class Pie extends Bakery {}
 
class Tart extends Bakery {}
 
interface Box<T> {
    public void put(T item);
    public T get();
}

There is Packer class available, but it is designed with business rule violation and lacks implementation. Correct the Packer code to ensure that:

  • Any kind of Bakery could be repacked to the Box with more basic type (e.g. from box with Pie to box with Food)
  • Basic stuff like food can't be repacked into narrowly typed Box'es (e.g. with Cakes)
  • Arbitrary stuff like Strings or Objects can't be repacked without compile-time errors or warnings
  • Repacking actually happens
/**
    This packer has too much freedom and could repackage stuff in wrong direction.
    Fix method types in signature and add implementation. 
*/

class Packer {

    public void repackage(Box<? super Bakery> to, Box<? extends Bakery> from) {
	to.put(from.get());
    }

}

List multiplicator:

You are provided with the backbone of ListMultiplicator class that has multiple methods that take list and multiplies its content specified number of times. The original list content should be changed after method returns. The task is to add implementation to the method without changing its signature.

You are guaranteed that:

  • list is not null
  • n equals or greater than zero

n stands for the number of times the original list repeated in the result. So if n equals zero the resulting list should be empty.

/**
    Class to modify
*/

class ListMultiplicator {

    /**
        Multiplies original list provided number of times

        @param list list to multiply
        @param n times to multiply, should be zero or greater
    */

    public static void multiply(List<?> list, int n) {
        multiplyHelper(list, n);
    }
    
    private static <T> void multiplyHelper(List<T> list, int n) {
        final List<T> temp = list;
        List<T> additions = new ArrayList<>();
        if (n > 1) {
            for (int i = 1; i < n; i++) {
                temp.forEach(elem -> additions.add(elem));                
            }
            list.addAll(additions);
        } else if (n == 0) {
            list.clear();
        }
    }
}