CS 70

What is Polymorphism?

  • Cat speaking

    The learning goals mention “polymorphism”. What is that exactly?

Breaking it down literally, the word means

  • poly — many
  • morph — form (or type)
  • ism — a specific practice, system, or philosophy

So from reading the word, it's a system or practice (perhaps even a philosophy) related to “many forms/types”.

  • Cat speaking

In the domain of programming languages, a function is polymorphic if it has at least one parameter that accepts arguments of more than one type.

  • Goat speaking

    Meh. That sounds super vague.

  • LHS Cow speaking

    It is.

  • Cat speaking

    Are we talking about just one function the programmer wrote, or just the same name being used but it's really different functions that get called?

  • LHS Cow speaking

    Both! There are actually several kinds of polymorphism.

  • Goat speaking

    Meh. Of course there are…

  • LHS Cow speaking

    Let's see what kinds you can think of!

What are some ways we've seen to have a function take on different behavior (in terms of, say, the type of the parameters it takes) in different places?

Templates: Parametric Polymorphism

Suppose we write this function template:

template <typename T>
const T& max(const T& x, const T& y) {
    if (x > y) {
        return x;
    } else {
        return y;
    }
}

This max() function takes arguments of many types because we have factored out the type of the arguments as a type parameter (T).

These days, rather than calling it “parametic polymorphism”, people often instead say that max() is generic.

Notice that instantiations of our max template are made at compile time, so this kind of polymorphism can also be described as static.

Overloading: Ad Hoc Polymorphism

We could instead define specific max() functions for particular types. For example, we could have a max() for ints and a max() for doubles.

Overloading describes the situation where the same function name is reused for multiple (different!) functions behind the scenes. Instead of needing to write intMax() and doubleMax(), we can give them both the same name, max(), and have the compiler figure out which one to call based on the types it saw when we called it. Pass in two ints and it calls the integer max() function, pass in two doubles and it'll call the floating-point max() function.

  • Hedgehog speaking

    What happens if you call max(1, 3.14)? Will that work?

  • LHS Cow speaking

    The compiler will pick the version of the function that matches best—that is, the one that needs the least amount of promotion/conversion that has to be done with the values passed into a particular call to the function name.

  • RHS Cow speaking

    But we don't really need to get into the weeds here.

  • Rabbit speaking

    Hmph.

We've seen overloading ever since we started using numbers. When you write x + y, the compiler will use different code depending on the type(s) of x and y. But there isn't a generic + function that works on anything, only ones for the types that have operator+ defined.

If we want + for some new type (say we want + for two TreeSet types), we can define it, but if we don't write it, it won't exist.

This kind of polymorphism is much less expansive than templates (a.k.a. genericity or parametric polymorphism). It only works for the specific types we've defined it for. So it's called ad hoc polymorphism.

Inheritance: Subtype Polymorphism

  • Jo speaking

    In Java, you can make subclasses! You can say Student is a subclass of Person and then every function that takes a Person can be passed a Student!! And we can say jo.height() whether jo is a Person or a Student!!!

  • Bjarne speaking

    C++ has the same ideas. But I could never keep “subclass” and “superclass” straight in my head, so instead we say that Person is a class that is derived from Student.

  • Hedgehog speaking

    Argghh… I don't remember any of that Java stuff.

  • LHS Cow speaking

    No worries, we'll go over it because it's not exactly the same in C++ anyway.

When Person is derived from Student, then Student is a subtype of Person. We use the term “subtype” similarly to “subset”: every Student value can also be seen as a Person value (but not vice versa).

We first saw (a limited form of) subtyping when we talked about promotion for integer types. For example, we can say that short is a subtype of int and float is a subtype of double.

Any function that wants a particular type can always be given a subtype of that type and still work. A function that wants a Person can be given a Student and a function that wants a double can be given a float.

(When logged in, completion status appears here.)