001package beginner;
002
003import com.sandwich.koan.Koan;
004
005import static com.sandwich.koan.constant.KoanConstants.__;
006import static com.sandwich.util.Assert.assertEquals;
007
008public class AboutInheritance {
009
010    abstract class Animal {
011        abstract public String makeSomeNoise();
012    }
013
014    class Cow extends Animal {
015        @Override
016        public String makeSomeNoise() {
017            return "Moo!";
018        }
019    }
020
021    class Dog extends Animal {
022        @Override
023        public String makeSomeNoise() {
024            return "Woof!";
025        }
026
027        public boolean canFetch() {
028            return true;
029        }
030    }
031
032    class Puppy extends Dog {
033        @Override
034        public String makeSomeNoise() {
035            return "Squeak!";
036        }
037        public boolean canFetch() {
038            return false;
039        }
040    }
041
042    @Koan
043    public void methodOverloading() {
044        Cow bob = new Cow();
045        Dog max = new Dog();
046        Puppy barney = new Puppy();
047        assertEquals(bob.makeSomeNoise(), __);
048        assertEquals(max.makeSomeNoise(), __);
049        assertEquals(barney.makeSomeNoise(), __);
050
051        assertEquals(max.canFetch(), __);
052        assertEquals(barney.canFetch(), __);
053        // but can Bob the Cow fetch?
054    }
055
056    @Koan
057    public void methodOverloadingUsingPolymorphism() {
058        Animal bob = new Cow();
059        Animal max = new Dog();
060        Animal barney = new Puppy();
061        assertEquals(bob.makeSomeNoise(), __);
062        assertEquals(max.makeSomeNoise(), __);
063        assertEquals(barney.makeSomeNoise(), __);
064        // but can max or barney (here as an Animal) fetch?
065        // try to write it down here
066    }
067
068    @Koan
069    public void inheritanceHierarchy() {
070        Animal someAnimal = new Cow();
071        Animal bob = new Cow();
072        assertEquals(someAnimal.makeSomeNoise().equals(bob.makeSomeNoise()), __);
073        // cow is a Cow, but it can also be an animal
074        assertEquals(bob instanceof Animal, __);
075        assertEquals(bob instanceof Cow, __);
076        // but is it a Puppy?
077        assertEquals(bob instanceof Puppy, __);
078    }
079
080    @Koan
081    public void deeperInheritanceHierarchy() {
082        Dog max = new Dog();
083        Puppy barney = new Puppy();
084        assertEquals(max instanceof Puppy, __);
085        assertEquals(max instanceof Dog, __);
086        assertEquals(barney instanceof Puppy, __);
087        assertEquals(barney instanceof Dog, __);
088    }
089
090    // TODO overriding
091//
092//    abstract class ParentTwo {
093//        abstract public Collection<?> doStuff();
094//    }
095//
096//    class ChildTwo extends ParentTwo {
097//        public Collection<?> doStuff() {
098//            return Collections.emptyList();
099//        }
100//
101//        ;
102//    }
103//
104//    @Koan
105//    public void overriddenMethodsMayReturnSubtype() {
106//        // What do you need to change in order to get rid of the type cast?
107//        // Why does this work?
108//        List<?> list = (List<?>) new ChildTwo().doStuff();
109//        assertEquals(list instanceof List, __);
110//    }
111}