Violate the method that checks a list of generic objects

Viewed 77

This is a task from Hyperskill.org.

The instructions for the task are;

You need to add implementation to Violator.defraud() method that will do the following:

Create List of Boxes according to method signature Put Paper object in at least one Box in the list The resulting list should pass NaiveQualityControl check You shouldn't change method signature or change code of any other classes, just add implementaiton to defraud method.

/* This class and its subclasses should pass quality check */
class Bakery {}

class Cake extends Bakery {}

/* But this should not */
class Paper {}

/* These boxes are used to pack stuff */
class Box<T> {
    void put(T item) { /* implementation omitted */ }
    T get() { /* implementation omitted */ }
}

/* This quality checker ensures that boxes for sale contain Bakery and anything else */
class NaiveQualityControl {

  public static boolean check(List<Box<? extends Bakery>> boxes) {
    /* Method signature guarantees that all illegal 
       calls will produce compile-time error... or not? */  
    return true;  
  }

}

This is the method to implement;

class Violator {

    public static List<Box<? extends Bakery>> defraud() {
        // Add implementation here
    }

}

So far I have got this;

public static List<Box<? extends Bakery>> defraud() {
        List<Box<? extends Bakery>> boxList = new ArrayList<>();

        Box<Paper> paperBox = new Box<>();
        Box<Bakery> bakeryBox = new Box<>();
        Box<Cake> cakeBox = new Box<>();

        boxList.add(bakeryBox);
        boxList.add(cakeBox);
        boxList.add(paperBox); // compile time error, required type <? extends Bakery>

        return boxList;
    }

Obviously this won't run. I have tried using Object as a type but that is out of type bounds for <? extends Bakery>. I can't cast a paperBox to a <? extends Bakery Box type.

1 Answers

You can get around it by using raw types (by dropping the generics for boxList). In fact, if you do this, you can add just about any type of Object:

public List<Box<? extends Bakery>> defraud() {
    List<Box<? extends Bakery>> boxList = new ArrayList<>();

    Box<Paper> paperBox = new Box<>();
    Box<Bakery> bakeryBox = new Box<>();
    Box<Cake> cakeBox = new Box<>();

    boxList.add(bakeryBox);
    boxList.add(cakeBox);

    List rawTypedList = boxList;    // Drop the generics to use raw types. 
    rawTypedList.add(paperBox);
    rawTypedList.add(new Object()); // Acutally, you can add any object, not just Boxes.

    return boxList;
}

You'll get a warning from the compiler or IDE for using raw types though - it is considered bad practice.

Related