Herança (Java)

Aula 7

Objetivo da Aula

“Apresentar herança no contexto da linguagem Java”

Lembrando Herança de Classes

Herança de classes é o processo de se criar uma classe (a subclasse) a partir de outra já existente (a superclasse), herdando as suas características (comportamento e estado).

Declaração de Herança


class Individuo { //superclasse de Aluno e Professor
  protected String nome;
  public String getNome() { return nome; }
  public Individuo(String nome){ this.nome = nome; }
}
class Aluno extends Individuo { //subclasse de Individuo
  //...
  public void fazEEntregaRelatorio() { /*codigo*/ }
}
class Professor extends Individuo { //subclasse de Individuo
  //...
  public void corrigeRelatorios() { /*codigo*/ }
}

Detalhes

O que se pode fazer numa subclasse


class Aluno extends Individuo {
  int matricula; //definir novas variáveis
  public void umCoisaQueOAlunoFaz() { //definir novos métodos
    System.out.println(getNome()); //chamar métodos herdados
    nome = "novo nome"; //Usar as variáveis herdadas normalmente
  }
  public String getNome() { //sobrescrever métodos
    return "Aluno " + super.getNome() 	//super usado para desambiguar
					//chamadas à superclasse
  }
  //tudo mais que se pode fazer numa classe comum (última aula)
}

Entendendo polimorfismo

  • Poder tratar um objeto de uma classe como um objeto de sua superclasse.
    • Esconde detalhes que não são relevantes num contexto
    • Permite um certo dinamismo a linguagens estáticas
  • Mostrar exemplo no BlueJ

Entendendo polimorfismo (2)


public static void imprimeNome(Individuo ind) { 
  //ind pode ser Aluno, Professor ou Individuo
  System.out.println (ind.getNome());
}

Aluno aluno = new Aluno("João");
Professor prof = new Professor("José");
imprimeNome(aluno);
imprimeNome(prof);

Entendendo polimorfismo (3)


public void fazAlgo(Individuo ind) {
  //só posso usar a interface de Individuo em ind
  ind.fazEEntregaRelatorio(); //gera erro mesmo se passarmos um Aluno
}

Entendendo polimorfismo (4)

O contrário não é válido! (não se pode tratar um objeto de uma classe como objeto de sua subclasse).
“Um aluno é um indivíduo, mas um indivíduo nem sempre é um aluno”.


Individuo ind = new Aluno("João"); //ok
Individuo ind2 = new Professor("João"); //ok
Aluno aluno = new Indivíduo("José"); //gera erro

Polimorfismo no lab1


class Relatorio {
  //...
  public Relatorio(double qualidade, double originalidade, Aluno aluno) { /* ...*/ }
  //...
}

AlunoSafoPreguicoso alunoS = new AlunoSafoPreguicoso('João');
AlunoEsforcado alunoE = new AlunoEsforcado('Manuel');
Relatorio rela1 = new Relatorio(0.6, 0.7, alunoS)
Relatorio rela1 = new Relatorio(0.6, 0.7, alunoE)

Casting Explícito

Permite ‘converter’ um objeto mais geral (superclasse) para um objeto mais específico (subclasse).


  Individuo ind = new Professor("João"); // casting implicito
  Professor prof = (Professor) ind; // diz ao compilador que ind é um Professor
  Aluno aluno = (Aluno) ind; //gera erro de runtime pois ind não é um Aluno.

Casting Explícito(2)

Como em C, os tipos nativos podem sofrer conversão com casting.


double d = 1.23;
float f = 1.43f + (float) d

Overriding versus Hiding na herança

Overriding versus Hiding na herança (2)


class Animal {
    public static void testClassMethod() {
        System.out.println("The class method in Animal.");
    }
    public void testInstanceMethod() {
        System.out.println("The instance method in Animal.");
    }
}

Overriding versus Hiding na herança (3)


class Cat extends Animal {
    public static void testClassMethod() {
        System.out.println("The class method in Cat.");
    }
    public void testInstanceMethod() {
        System.out.println("The instance method in Cat.");
    }
    public static void main(String[] args) {
        Cat myCat = new Cat();
        Animal myAnimal = myCat;
        Animal.testClassMethod();
        myAnimal.testInstanceMethod();
    }
}

Herança e controle de acesso (métodos)

O controle de acesso aos métodos pode ser “ampliado”, mas nunca restrito.


class SuperClasse {
  protected void umMetodo(){/*...*/}
  public void outroMetodo(){/*...*/}
}
class SubClasse extends SuperClasse {
  public void umMetodo(){/*...*/} //ok - ampliado
  private void outroMetodo(){/*...*/}  // erro! - não pode ser restrito
}

Super

A keyword super (de forma semelhante ao @this@) pode ser usada para:

Super(2)


class AlunoSafoPreguicoso extends Aluno
  public AlunoSafoPreguicoso(String nome, RelaQueue queue) {
    super(nome, queue);
  }
}

Construtores e Herança

Final

Podemos impedir que classes sejam estendidas e métodos sejam sobreescritos com o keyword final.


final class SemSubClasses { /*...*/ }
class UmaClasse {
    final void semOverriding() { /* ... */ }
}

Abstract

Classes abstratas:

Abstract – Exemplo


public abstract class Aluno {
    //...
    public abstract float getInteligencia();
    public abstract float getDedicacao();
    public String getNome() { return nome; }
}

public class AlunoEsforcado {
    //...
    public float getInteligencia() { return 0.5; }
    public float getDedicacao(){ return 1; }
}

Interfaces

Em uma linha: são como classes abstratas, com todos métodos públicos abstratos, e com herança múltipla.


public interface GroupedInterface extends Interface1,
                                        Interface2, Interface3 {
   double E = 2.718282;  // constante
   void doSomething (int i, double x); //assinatura de método
   int doSomethingElse(String s); //assinatura de método
}

Implementando uma interface


public interface ComComportamento {
   double getInteligencia();
   double getDedicacao();
}

public class AlunoInteligente extends Aluno implements ComComportamento {
  //...
  double getInteligencia() {/*implementação*/};
  double getDedicacao(){/*implementação*/};
}
public class Cachorro implements ComComportamento { /*...*/}

Interfaces são como classes

Pode-se usar o polimorfismo e tratar a interface como um tipo.


static void dizSeEhInteligente(ComComportamento obj) {
  if (obj.getInteligencia() > 0.9) System.out.println ("Isto é um gênio!");
}
static void main(String[] args) {
  AlunoInteligente aluno = new AlunoInteligente('Joao');
  Cachorro pet = new Cachorro('Pluto')
  dizSeEhInteligente(pet);
  dizSeEhInteligente(aluno);
}

Packages

Conjuntos de classes relacionadas. Ex.: java.io, java.util.


package graphics;
public class Retangle {/*disponível fora do pacote*/}
class RetanglePainter {/*só disponível no pacote*/}

Packages (2)

Usando uma classe dentro de um pacote:


  java.util.Random r = new java.util.Random();
  //ou
  import java.util.Random;
  java.util.Random r = new java.util.Random();
  //pode também importar todas as classes (públicas) de um package
  import java.util.*;