001package beginner;
002
003import com.sandwich.koan.Koan;
004
005import static com.sandwich.koan.constant.KoanConstants.__;
006import static com.sandwich.util.Assert.assertEquals;
007import static com.sandwich.util.Assert.fail;
008
009@SuppressWarnings("unused")
010public class AboutCasting {
011
012    @Koan
013    public void longPlusInt() {
014        int a = 6;
015        long b = 10;
016        Object c = a + b;
017        assertEquals(c, __);
018        assertEquals(c instanceof Integer, __);
019        assertEquals(c instanceof Long, __);
020    }
021
022    @Koan
023    public void forceIntTypecast() {
024        long a = 2147483648L;
025        // What happens if we force a long value into an int?
026        int b = (int) a;
027        assertEquals(b, __);
028    }
029
030    @Koan
031    public void implicitTypecast() {
032        int a = 1;
033        int b = Integer.MAX_VALUE;
034        long c = a + b; // still overflows int... which is the Integer.MIN_VALUE, the operation occurs prior to assignment to long
035        assertEquals(c, __);
036    }
037
038    interface Sleepable {
039        String sleep();
040    }
041
042    class Grandparent implements Sleepable {
043        public String sleep() {
044            return "zzzz";
045        }
046    }
047
048    class Parent extends Grandparent {
049        public String complain() {
050            return "TPS reports don't even have a cover letter!";
051        }
052    }
053
054    class Child extends Parent {
055        public String complain() {
056            return "Are we there yet!!";
057        }
058    }
059
060    @Koan
061    public void downCastWithInheritance() {
062        Child child = new Child();
063        Parent parentReference = child; // Why isn't there an explicit cast?
064        assertEquals(child instanceof Child, __);
065        assertEquals(parentReference instanceof Child, __);
066        assertEquals(parentReference instanceof Parent, __);
067        assertEquals(parentReference instanceof Grandparent, __);
068    }
069
070    @Koan
071    public void downCastAndPolymorphism() {
072        Child child = new Child();
073        Parent parentReference = child;
074        // If the result is unexpected, consider the difference between an instance and its reference
075        assertEquals(parentReference.complain(), __);
076    }
077
078    @Koan
079    public void upCastWithInheritance() {
080        Grandparent child = new Child();
081        Parent parentReference = (Parent) child; // Why do we need an explicit cast here?
082        Child childReference = (Child) parentReference; // Or here?
083        assertEquals(childReference instanceof Child, __);
084        assertEquals(childReference instanceof Parent, __);
085        assertEquals(childReference instanceof Grandparent, __);
086    }
087
088    @Koan
089    public void upCastAndPolymorphism() {
090        Grandparent child = new Child();
091        Parent parent = (Child) child;
092        // Think about the result. Did you expect that? Why?
093        // How is that different from above?
094        assertEquals(parent.complain(), __);
095    }
096
097    @Koan
098    public void classCasting() {
099        try {
100            Object o = new Object();
101            ((Sleepable) o).sleep(); // would this even compile without the cast?
102        } catch (ClassCastException x) {
103            fail("Object does not implement Sleepable, maybe one of the people classes do?");
104        }
105    }
106
107    @Koan
108    public void complicatedCast() {
109        Grandparent parent = new Parent();
110        // How can we access the parent's ability to "complain" - if the reference is held as a superclass?
111        assertEquals("TPS reports don't even have a cover letter!", __);
112    }
113
114}