14.4. Herança e construtores

De acordo com a secção anterior, um objeto do tipo JogoComObjetivo tem três atributos de instância:

A imagem seguinte representa o estado pretendido de um objeto do tipo JogoComObjetivo acabado de criar (com valor inicial de "Spiral" para a designação e para o objetivo de 30).

 

Relembre, da secção 10.3., o que acontece quando uma instrução de criação de um objeto é executada:

A criação de uma instância de uma classe é feita em três passos:

  1. reserva e afetação de memória para o objeto (contando com o espaço a ocupar por cada um dos seus atributos);

  2. inicialização desses atributos com valores por omissão:

    • zero para atributos de tipos primitivos numéricos,
    • false para boolean, e
    • null para atributos cujo tipo não é primitivo;
  3. invocação do construtor indicado, sobre o objeto acabado de criar.

O objetivo principal dos construtores é o de inicializar os atributos de um objeto acabado de criar com valores diferentes dos valores por omissão.

Se o papel de um construtor declarado numa classe é o de inicializar os atributos nela definidos com valores específicos, então o construtor da classe JogoComObjetivo deveria inicializar todos os atributos do novo objeto.

Mas os dois atributos herdados estão definidos como private na classe Jogo, ou seja, eles só estão acessíveis a partir de código da própria classe Jogo. Então, como fazer para inicializar esses atributos a partir do construtor JogoComObjetivo?

Esse é o papel da instrução super(designacao); no construtor da classe JogoComObjetivo:

O que esta instrução faz é invocar, sobre o objeto acabado de criar, o construtor definido na superclasse – neste caso, na classe Jogo – para que os atributos aí definidos possam ser inicializados adequadamente.

Neste caso, como o construtor da classe Jogo tem um parâmetro – a designação – a instrução super(…) deve fornecer um valor para esse parâmetro.

Como é suposto esse valor ser decidido, para cada jogo, por quem cria o objeto, então o construtor da subclasse também requer um parâmetro com esse significado, para além de um parâmetro que recebe o valor da pontuação objetivo.

Este construtor usa o valor do primeiro parâmetro na invocação do construtor da sua superclasse e usa o valor do segundo parâmetro para inicializar o atributo objetivo.

No fim da execução do construtor da classe JogoComObjetivo, o novo objeto já terá todos os seus atributos inicializados (tanto os herdados como aquele que a própria classe definiu).

 

No Java, qualquer construtor definido explicitamente numa subclasse tem como primeira instrução, obrigatoriamente, a invocação de um construtor da sua superclasse. Esta instrução pode ser explícita ou implícita (mais adiante).

Como já exemplificado, uma forma de invocar o construtor da superclasse, a partir do corpo do construtor da subclasse, é através de uma instrução da forma super(...), onde representa os valores para os parâmetros desse construtor:

 

Deve lembrar-se de que os construtores das classes Jogador e Jogo (capítulos 10 e 11, respetivamente) não seguem esta regra… estes construtores aparentemente não definem como primeira instrução (nem nenhuma das seguintes) uma que invoque o construtor da sua superclasse. No entanto estas classes têm uma superclasse: a classe Object.

Quando a primeira instrução de um construtor não é uma invocação de um construtor da superclasse,

Se fizessemos isso no caso da classe JogoComObjetivo,

o compilador iria acrescentar, como primeira instrução, a instrução super();.

Mas… na classe Jogo não existe nenhum construtor sem parâmetros. Só existe um construtor que tem um parâmetro do tipo String. Sabendo isto, o compilador daria erro.

 

Voltando aos construtores das classes Jogador e Jogo: como não têm uma primeira instrução em que é invocado um construtor da sua superclasse (que é Object, como já vimos), o compilador vai acrescentar a instrução super();. Aqui não há problema pois a classe Object tem um único construtor, o qual não tem parâmetros.

 

 


 

Anterior: 14.3. Subtipos

Seguinte: 14.5. Invocação de métodos herdados