How 3 of your resources explain polymorphism, side by side.
CONCEPT
SOURCES · CHOOSE 2–3
JAVA PROGRAMMING ESSENTIALS
One call, many behaviours
Chapter 8 · Polymorphism · p. 142
Compiler-checked: a declared supertype, with the JVM choosing the implementation at runtime.
A List<Shape> holds a Circle, a Square and a Triangle. One loop calls area() on each, and the JVM picks the right version. The declared type decides which calls are allowed; the actual object decides which code runs. Interfaces such as Payable extend this to unrelated classes.
List<Shape> shapes = List.of(new Circle(2), new Square(3));
for (Shape s : shapes) total += s.area(); // dynamic dispatch
Behaviour-first: duck typing means any object with the right method will do.
A function that calls item.area() works with any object that has an area method. Overriding still gives each subclass its own version, but Python checks for the method only at runtime. typing.Protocol can document the expected behaviour.
def total_area(items):
return sum(item.area() for item in items) # any object with area()
Language-neutral: the same principle shown side by side in Java and Python.
Polymorphism lets one piece of code operate on many types. Java expresses it through a declared supertype resolved at runtime; Python through duck typing. Both depend on inheritance or interfaces for a shared type and on encapsulation to hide implementation details.