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}