001package intermediate;
002
003import com.sandwich.koan.Koan;
004
005import static com.sandwich.koan.constant.KoanConstants.__;
006import static com.sandwich.util.Assert.assertEquals;
007
008public class AboutInnerClasses {
009
010    interface Ignoreable {
011        String ignoreAll();
012    }
013
014    class Inner {
015        public String doStuff() {
016            return "stuff";
017        }
018
019        public int returnOuter() {
020            return x;
021        }
022    }
023
024    @Koan
025    public void creatingInnerClassInstance() {
026        Inner someObject = new Inner();
027        assertEquals(someObject.doStuff(), __);
028    }
029
030    @Koan
031    public void creatingInnerClassInstanceWithOtherSyntax() {
032        AboutInnerClasses.Inner someObject = this.new Inner();
033        assertEquals(someObject.doStuff(), __);
034    }
035
036    private int x = 10;
037
038    @Koan
039    public void accessingOuterClassMembers() {
040        Inner someObject = new Inner();
041        assertEquals(someObject.returnOuter(), __);
042    }
043
044    @Koan
045    public void innerClassesInMethods() {
046        class MethodInnerClass {
047            int oneHundred() {
048                return 100;
049            }
050        }
051        assertEquals(new MethodInnerClass().oneHundred(), __);
052        // Where can you use this class?
053    }
054
055    class AnotherInnerClass {
056        int thousand() {
057            return 1000;
058        }
059
060        AnotherInnerClass crazyReturn() {
061            class SpecialInnerClass extends AnotherInnerClass {
062                int thousand() {
063                    return 2000;
064                }
065            }
066            ;
067            return new SpecialInnerClass();
068        }
069    }
070
071    @Koan
072    public void innerClassesInMethodsThatEscape() {
073        AnotherInnerClass ic = new AnotherInnerClass();
074        assertEquals(ic.thousand(), __);
075        AnotherInnerClass theCrazyIC = ic.crazyReturn();
076        assertEquals(theCrazyIC.thousand(), __);
077    }
078
079    int theAnswer() {
080        return 42;
081    }
082
083    @Koan
084    public void creatingAnonymousInnerClasses() {
085        AboutInnerClasses anonymous = new AboutInnerClasses() {
086            int theAnswer() {
087                return 23;
088            }
089        };// <- Why do you need a semicolon here?
090        assertEquals(anonymous.theAnswer(), __);
091    }
092
093    @Koan
094    public void creatingAnonymousInnerClassesToImplementInterface() {
095        Ignoreable ignoreable = new Ignoreable() {
096            public String ignoreAll() {
097                return null;
098            }
099        }; // Complete the code so that the statement below is correct.
100        // Look at the koan above for inspiration
101        assertEquals(ignoreable.ignoreAll(), "SomeInterestingString");
102        // Did you just created an object of an interface type?
103        // Or did you create a class that implemented this interface and
104        // an object of that type?
105    }
106
107    @Koan
108    public void innerClassAndInheritance() {
109        Inner someObject = new Inner();
110        // The statement below is obvious...
111        // Try to change the 'Inner' below to "AboutInnerClasses'
112        // Why do you get an error?
113        // What does that imply for inner classes and inheritance?
114        assertEquals(someObject instanceof Inner, __);
115    }
116
117    class OtherInner extends AboutInnerClasses {
118    }
119
120    @Koan
121    public void innerClassAndInheritanceOther() {
122        OtherInner someObject = new OtherInner();
123        // What do you expect here?
124        // Compare this result with the last koan. What does that mean?
125        assertEquals(someObject instanceof AboutInnerClasses, __);
126    }
127
128    static class StaticInnerClass {
129        public int importantNumber() {
130            return 3;
131        }
132    }
133
134    @Koan
135    public void staticInnerClass() {
136        StaticInnerClass someObject = new StaticInnerClass();
137        assertEquals(someObject.importantNumber(), __);
138        // What happens if you try to access 'x' or 'theAnswer' from the outer class?
139        // What does this mean for static inner classes?
140        // Try to create a sub package of this package which is named 'StaticInnerClass'
141        // Does it work? Why not?
142    }
143
144    @Koan
145    public void staticInnerClassFullyQualified() {
146        AboutInnerClasses.StaticInnerClass someObject = new AboutInnerClasses.StaticInnerClass();
147        assertEquals(someObject.importantNumber(), __);
148    }
149
150}