Problem Statment:
You are asked to perform a security audit in a baking company. Their products are represented by Bakery class and its different subclasses like Cake and LemonTart. All the pastries are sold in nice boxes. Prior to being released to the customer, all boxes are checked with carefully designed NaiveQualityControl class. However, recently a number of mistakes happened and unedible things were packed in boxes and escaped the quality check.
A short look at NaiveQualityControl led you to the conclusion that it's quite easy to provide NaiveQualityControl with Box filled with Paper that will pass QC. Now your task is to demonstrate this mistake. Here's the code:
/* This class and its subclasses should pass quality check */
class Bakery {}
class Cake extends Bakery {}
/* This one 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;
}
}
You need to add implementation to Violator.defraud() method that will do the following:
- Create List of Boxes<? extends Bakery> according to the method signature
- Put Paper object in at least one Box in the list
- The resulting list should pass NaiveQualityControl check
My solution:
import java.util.ArrayList;
class Violator {
public static List<Box<? extends Bakery>> defraud() {
Paper paper = new Paper();
Box paperBox = new Box();
paperBox.put(paper);
List<Box<? extends Bakery>> boxes = new ArrayList<>();
boxes.add(paperBox);
return boxes;
}
}
My solution is working but I came up with it using hit and trial menthod so I have no idea why is this working. How Paper class even though not extending Bakery class still manages to get added in boxes list?
One more doubt, why this solution isi't working?
import java.util.ArrayList;
class Violator {
public static List<Box<? extends Bakery>> defraud() {
Paper paper = new Paper();
Box<? extends Object> paperBox = new Box<>();// It should accept any type of box as any reference type is subclass of Object class...right?
paperBox.put(paper);
List<Box<? extends Bakery>> boxes = new ArrayList<>();
boxes.add(paperBox);
return boxes;
}
}
Error:
Compilation error
Main.java:7: error: incompatible types: Paper cannot be converted to CAP#1
paperBox.put(paper);
^
where CAP#1 is a fresh type-variable:
CAP#1 extends Object from capture of ? extends Object
Main.java:9: error: incompatible types: Box<CAP#1> cannot be converted to Box<? extends Bakery>
boxes.add(paperBox);
^
where CAP#1 is a fresh type-variable:
CAP#1 extends Object from capture of ? extends Object
Note: Some messages have been simplified; recompile with -Xdiags:verbose to get full output
2 errors