Press enter to see results or esc to cancel.

Como sobrescrever métodos em Java?

Sobrescrever métodos em Java é como herdar habilidades dos seus pais, mas dar a sua personalidade para essas habilidades.

Meu pai foi quem me ensinou a dirigir. Apesar de ter aprendido com ele, eu não dirijo exatamente como ele. Eu tenho alguns comportamentos diferentes dos dele, principalmente em relação à forma de estacionar. Então, eu e meu pai sabemos como estacionar um carro, mas eu faço isso de uma forma diferente da que ele me ensinou.

Assim como eu tenho comportamentos que foram passados pelo meu pai para mim, as classes herdam comportamentos de outras classes. E assim como eu estaciono um carro de forma diferente do meu pai, uma classe herdada pode implementar o mesmo comportamento da classe pai de forma diferente.

Redefinir o comportamento herdado de uma classe é chamado de sobrescrita de método. Os métodos sobrescritos também são chamados de métodos polimórficos. Neste post aprenderemos como sobrescrever métodos em Java.

Necessidade da sobrescrita de métodos

Imagine que estamos a desenvolver um programa para uma locadora de filmes e criamos a seguinte classe Filme:

public class Filme {
    public void alugarFilme(int dias){
          if ((dias > 0) && (dias <= 5)){
              System.out.println("Aluguel feito.");
          }else{
              System.out.println("Não é possível alugar um filme por menos de 0 dias ou mais de 5 dias.");
          }
    }
}

Essa classe define o comportamento para alugar um filme por meio do método alugarFilme. Repare que o filme pode ser alugado desde que a quantidade de dias seja maior que 0 e menor ou igual a 5.

Abaixo está outra classe, Filme24Horas, que herda a classe Filme. Ela precisa sobrescrever o método alugarFilme porque um filme 24 horas não pode ser alugado por mais de 1 dia. Veja como conseguimos mudar esse comportamento:

public class Filme24Horas extends Filme {

    @Override
    public void alugarFilme(int dias) {
        if ((dias > 0) && (dias <=1)){
            System.out.println("Aluguel feito.");
        }else{
            System.out.println("Filme 24 horas deve ser alugado por no máximo 1 dia.");
        }
    }
}

A classe fez uso de uma anotação opcional, @Override, que serve para avisar o compilador que o método logo após faz a sobrescrita de um método da classe pai. Caso o método faça a sobrescrita incorretamente, o compilador lança um erro com uma descrição assim:

Método não sobrescreve ou implementa um método de um super-tipo.

Então, apesar de ser opcional, a anotação @Override ajuda bastante. Ela vai te avisar caso o método não possa ser sobrescrito ou se você está fazendo uma sobrecarga ao invés da sobrescrita.

Sintaxe para a sobrescrita

No exemplo da locadora, nós já percebemos que para sobrescrever um método devemos escrever outro método com a mesma assinatura do anterior. A assinatura é o nome do método e a sua lista de parâmetros. Falamos bastante sobre a assinatura de métodos neste post.

Também devemos observar bem a declaração do método: Modificadores de não-acesso, modificadores de acesso, tipo de retorno, nome do método, lista de parâmetros, e a lista das exceções que podem ser lançadas.

Modificadores de não-acesso

Uma classe filha não pode sobrescrever um método marcado como final na classe mãe. O código abaixo não compila:

public class Filme {
    public final void alugarFilme(int dias){}
}

class Filme24Horas extends Filme {
    public void alugarFilme(int dias) {}
}

O uso da palavra reservada final na declaração de um método serve para isso mesmo. Impedir que ele seja sobrescrito por outro método.

Modificadores de acesso

Uma classe filha não pode tornar o método sobrescrito menos acessível do que ele é na classe mãe. O código abaixo não compila:

public class Filme {
    protected void alugarFilme(int dias){}
}

class Filme24Horas extends Filme {
    void alugarFilme(int dias) {}
}

O método alugarFilme da classe Filme24horas tem o modificador de acesso padrão, ou seja, só pode ser acessado por membros do mesmo pacote. O método alugarFilme da classe Filme tem o modificador de acesso protected, ou seja, só pode ser acessado por membros do mesmo pacote e membros que herdam a classe Filme dentro de pacotes diferentes. Padrão é mais restritivo do que protected

Revise os seus conhecimentos sobre os modificadores de acesso aqui.

Tipos de retorno

O método que faz a sobrescrita deve retornar o mesmo tipo ou uma subclasse do tipo de retorno do método sobrescrito. O código a seguir compila normalmente:

public class Filme {
    public Filme alugarFilme(int dias){}
}

class Filme24Horas extends Filme {
    public Filme24Horas alugarFilme(int dias) {}
}

O método alugarFilme da classe Filme retorna um Filme. O método alugarFilme da classe Filme24Horas sobrescreve corretamente o método da classe mãe pois retorna uma subclasse da classe Filme: Filme24Horas. Isso é chamado de retorno de tipos covariantes.

Lista de exceções

O método que faz a sobrescrita deve lançar nenhuma exceção verificada, a mesma exceção verificada ou uma subclasse da exceção verificada que o método sobrescrito lança. Exceções de tempo de execução e erros não seguem essa regra. Veja o exemplo abaixo:

public class Filme {
    public void alugarFilme(int dias){}
}

class Filme24Horas extends Filme {
    public void  alugarFilme(int dias) throws Exception{}
}

O código não compila. O método que faz a sobrescrita lança uma exceção verificada, mas o método sobrescrito não lança exceção verificada alguma.

Dicas finais

Uma classe só pode sobrescrever os métodos da classe mãe aos quais ela tem acesso. Por isso, o exemplo abaixo compila, mas não ocorre sobrescrita alguma.

public class Filme {
    private void alugarFilme(int dias){}
}

class Filme24Horas extends Filme {
    public void alugarFilme(int dias){}
}

São dois métodos completamente diferentes e um não tem nada a ver com o outro.

Só é possível sobrescrever métodos que não são estáticos, ou seja, não é possível sobrescrever métodos de classe. Veja a saída do código a seguir:

public class Filme {

    public static void alugarFilme(){
        System.out.println("Filme");
    }
}

class Filme24Horas extends Filme {

    public static void alugarFilme(){
        System.out.println("Filme 24 horas");
    }

    public static void main(String... args)
    {
        Filme filme24horas = new Filme24Horas();
        Filme filme = new Filme();

        filme24horas.alugarFilme();
        filme.alugarFilme();

    }
}
Filme
Filme

O exemplo acima mostra que o polimorfismo não ocorreu. Os métodos executados nos dois casos são da classe Filme.

Share on FacebookTweet about this on TwitterShare on Google+Share on LinkedInEmail this to someone
Comments

1 Comment

Alojamiento

Toda linguagem orientada a objetos permite a sobrescrita de metodos da super classe pela classe filha. Entretanto cada linguagem de programacao usa seus proprios meios para lidar com essa sobrescrita. O Java optou por usar o annotation @Override para os desenvolvedores que quiserem a seguranca citada no decorrer da resposta, entretanto, nada obriga o uso desse annotation.


Leave a Comment