This article is from the Object-Oriented Technology FAQ, by Bob Hathaway firstname.lastname@example.org with numerous contributions by others.
For a short answer:
Subtype Polymorphism, as opposed to Subclass Polymorphism, is the best answer
in OO. Parametric polymorphism is a related concept where this is also true,
but is of a different flavor (and usually requires object attributes by use.
See also section 2.1).
A type can be considered a set of values and a set of operations on those
values. This can insure type-safe programming. However, the representation of
types (classes in OO) can be separated from the notion of type allowing many
representations per type while still maintaining reasonable type-safety.
In many languages, a type has a single representation insuring all operations
performed on that type are well defined (statically bound) and providing for
efficiency by taking advantage of that representation wherever used. In many
OO languages, subclassing and dynamic binding provides for greater flexibility
by providing object specialization. However, in many OO languages classes are
used for assignment compatibility forcing an assigned object to inherit
(transitively) from any polymorphic object's class (inclusion polymorphism
based on class, or subclass polymorphism). This insures all operations to be
performed on any polymorphic object are satisfied by any replacing objects.
This also insures all types share a common representation, or at least a
common base interface specification.
By separating type from class, or representation (or perhaps separating class
from type, by the aforementioned definition of type), a replacing object must
satisfy the operations or type constraints of a polymorphic object (subtype
polymorphism) but are not required to do to do so by an inheritance relation
(subclass polymorphism), as is typical in most OOPLs. Dropping this
restriction is somewhat less type-safe, because accidental matches of method
signatures can occur, calling for greater care in use. [Black 86] discusses
this issue in Emerald. The same issue arises in parametric polymorphism
(generics/templates), as any method matching a required signature is accepted,
calling for careful matching of actual and formal generic parameters. The
difference between static and dynamic binding in OO and dynamic binding and
subtyping seems similar. A possible loss of semantic integrity/similarity is
contrasted with greater power.
It is possible to specify desired abstract properties of type specifications
with mechanisms similar to Eiffel's pre-, post-, and invariant conditions.
This helps to insure the semantic integrity of replacing objects and their
behavior. [Liskov 93] provides a recent exposition.
Abstract classes ([Stroustrup 91] and [Meyer 88]) in typing provide a facility
similar to subtype polymorphism; however, ACs require type compatible classes
to inherit from them, providing a subclass polymorphism facility, and ACs can
also specify representation. Subtyping is therefore most useful to avoid
spreading knowledge of classes throughout a system, which is a high priority
for loosely coupled modules and in distributed programming [Black 87].
The formal type system found in [Cardelli 85], Emerald/Jade [Black 86] and
[Raj 89], original trellis/Owl, an experimental C++ extension (See Appendix E,
Signatures), Sather (originally Eiffel-based), and an Eiffel superset
[Jones 92] are all examples of OO systems providing subtype polymorphism.
Functional languages such as ML, Russell, and Haskell provide a separation with
pure parametric polymorphism (as is also commonly found in OO languages in
addition to inclusion polymorphism).
See also [Cook 90], "Inheritance Is Not Subtyping", for a formal approach.