A variable's declared type describes the operations you can call. The object's runtime class decides which overridden instance method runs. That distinction lets a delivery batch hold Parcel references while express parcels supply a different charge. Adding a subclass doesn't require a second pricing loop.
Use an abstract class when subclasses share state or an algorithm but must fill in a missing operation. A constructor initializes the inherited state through super. A protected method can expose an extension point, and a final template method can keep validation in the required order. Fields and static methods don't dispatch like overridden instance methods. Don't duplicate the caller for every subtype. These exercises keep the calculation behind the base contract and check zero values, repeated types and rejected inputs.