Skip to main content
๐Ÿ“œ WAYPOINT LESSON

Polymorphic collections

โญโญ intermediateโณ 12 min read๐Ÿ“ Lesson 119 of 256

One reference type, many behaviors; the three cast cases; the Object trap.

Polymorphic collections โ€” the exam's synthesis shape:

ArrayList<Animal> zoo = new ArrayList<Animal>();
zoo.add(new Dog());          // Dog is-an Animal
zoo.add(new Animal());
zoo.add(new Dog());
for (Animal a : zoo) {
    System.out.println(a.speak());   // Woof, ..., Woof
}

One loop, three objects, two behaviors โ€” the reference type is Animal, the dispatch is per-object. Remove-by-content or count-by-behavior on such a list is the FRQ variant: "how many animals speak Woof?" is a for-each plus a dispatch trace.

The cast question. Animal a = new Dog(); Dog d = a; does NOT compile โ€” Animal is not known to be Dog. Dog d = (Dog) a; compiles and runs (a really holds a Dog). (Cat) a would compile but throw ClassCastException at runtime. The exam asks which of these three lines compiles/runs โ€” the rule: upcasts are free, downcasts need an explicit cast, wrong downcasts explode at runtime.

The Object trap. equals takes Object:

public boolean equals(Dog other) { ... }   // OVERLOAD, not override!

The parameter type must be Object to truly override. In AP scope you just need to recognize the shape: same signature = override; changed signature = overload.