Suponha que Shape declara um draw() método, seu Circle subclasse substitui este método, Shape s = new Circle(); acabou de ser executado e a próxima linha especifica s.draw();. Qual draw() método é chamado: Shape‘s draw() método ou Circle‘s draw() método? O compilador não sabe qual draw() método para chamar. Tudo o que ele pode fazer é verificar se um método existe na superclasse e verificar se a lista de argumentos da chamada do método e o tipo de retorno correspondem à declaração do método da superclasse. No entanto, o compilador também insere uma instrução no código compilado que, em tempo de execução, busca e usa qualquer referência que esteja em s para chamar o correto draw() método. Esta tarefa é conhecida como ligação tardia.

Criei um aplicativo que demonstra o polimorfismo de subtipo em termos de upcasting e ligação tardia. Este aplicativo consiste em Shape, Circle, Rectanglee Shapes classes, onde cada classe é armazenada em seu próprio arquivo de origem. A Listagem 1 apresenta as três primeiras classes.

Listagem 1. Declarando uma hierarquia de formas

class Shape
{
   void draw()
   {
   }
}

class Circle extends Shape
{
   private int x, y, r;

   Circle(int x, int y, int r)
   {
      this.x = x;
      this.y = y;
      this.r = r;
   }

   // For brevity, I've omitted getX(), getY(), and getRadius() methods.

   @Override
   void draw()
   {
      System.out.println("Drawing circle (" + x + ", "+ y + ", " + r + ")");
   }
}

class Rectangle extends Shape
{
   private int x, y, w, h;

   Rectangle(int x, int y, int w, int h)
   {
      this.x = x;
      this.y = y;
      this.w = w;
      this.h = h;
   }

   // For brevity, I've omitted getX(), getY(), getWidth(), and getHeight()
   // methods.

   @Override
   void draw()
   {
      System.out.println("Drawing rectangle (" + x + ", "+ y + ", " + w + "," +
                         h + ")");
   }
}

A Listagem 2 apresenta o Shapes classe de aplicação cuja main() O método direciona o aplicativo.