Herança

  • Capacidade das classes expandirem-se a partir das classes existentes.
  • Classe herdeira (subclasse)
    • possui os mesmos atributos da superclasse
    • herda acesso aos métodos desta superclasse
    • pode acrescentar novos atributos e métodos (extensão)

Considere a classe Lista que gerencia uma lista de números simples:


In [1]:
public class Lista {
   protected int vlista[] = new int[100];
   protected int ultimo = -1;
   
   public void adicionar(int item) {
      if (ultimo+1 < vlista.length) {
         ultimo++;
         vlista[ultimo] = item;
      }
   }
   
   public String toString() {
      String str = "";
      for (int l = 0; l <= ultimo; l++)
         str += vlista[l] + ((l < ultimo) ? ", " : "");
      return str;
   }
}


Out[1]:
com.twosigma.beaker.javash.bkr16b44ab1.Lista

In [2]:
Lista l = new Lista();
l.adicionar(10);
l.adicionar(15);
l.adicionar(20);
System.out.println("Lista: " + l);


Lista: 10, 15, 20
Out[2]:
null

Herança em Java

  • Classes ListaEstatistica e ListaUtil herdeiras de Lista
  • Estendem a classe Lista acrescentando métodos

Para se estabelecer que uma classe é herdeira de outra, após o nome da classe coloca-se a cláusula extends e o nome da superclasse:


In [3]:
public class ListaEstatistica extends Lista {

   public double soma() {
      double s = 0;
      for (int l = 0; l <= ultimo; l++)
         s += vlista[l];
      return s;
   }
   
   public double media() {
      return (ultimo >= 0)
            ? soma() / (ultimo+1) : 0;
   }

}


Out[3]:
com.twosigma.beaker.javash.bkr16b44ab1.ListaEstatistica

In [4]:
public class ListaUtil extends Lista {

   public void ordena() {
      int lastSwap = ultimo;
      while (lastSwap > 0) {
         int swap = 0;
         for (int v = 0; v < lastSwap; v++)
            if (vlista[v] > vlista[v+1]) {
               int aux = vlista[v];
               vlista[v] = vlista[v+1];
               vlista[v+1] = aux;
               swap = v;
            }
          lastSwap = swap;
      }
   }

}


Out[4]:
com.twosigma.beaker.javash.bkr16b44ab1.ListaUtil

Usando as classes herdeiras

  • Métodos herdados são ativados na superclasse de forma transparente, como se pertencessem à subclasse

In [5]:
ListaEstatistica le = new ListaEstatistica();
le.adicionar(10);
le.adicionar(20);
le.adicionar(5);
le.adicionar(35);
le.adicionar(15);
System.out.println("Soma: " + le.soma());
System.out.println("Media: " + le.media());

ListaUtil lu = new ListaUtil();
lu.adicionar(10);
lu.adicionar(20);
lu.adicionar(5);
lu.adicionar(35);
lu.adicionar(15);
lu.ordena();
System.out.println("Ordenado: " + lu);


Soma: 85.0
Media: 17.0
Ordenado: 5, 10, 15, 20, 35
Out[5]:
null

Acrescentando Atributos

  • Classe ListaUtil acrescentando um atributo (duplicatas)
  • Também foram acrescentados os respectivos métodos get e set para transformá-lo em uma propriedade

In [6]:
public class ListaUtil extends Lista {
   private boolean duplicatas = true;
   
   public boolean getDuplicatas() {
      return duplicatas;
   }
   
   public void setDuplicatas(boolean duplicatas) {
      this.duplicatas = duplicatas;
   }

   public void ordena() {
      int lastSwap = ultimo;
      while (lastSwap > 0) {
         int swap = 0;
         for (int v = 0; v < lastSwap; v++)
            if (vlista[v] > vlista[v+1]) {
               int aux = vlista[v];
               vlista[v] = vlista[v+1];
               vlista[v+1] = aux;
               swap = v;
            }
          lastSwap = swap;
      }
      
      if (!duplicatas) {
         int s = 0;
         for (int v = 0; v <= ultimo; v++)
            if (vlista[s] != vlista[v]) {
               s++;
               vlista[s] = vlista[v];
            }
         ultimo = s;
      }
   }

}


Out[6]:
com.twosigma.beaker.javash.bkr16b44ab1.ListaUtil

Ordenando sem duplicatas


In [7]:
ListaUtil lu = new ListaUtil();
lu.adicionar(10);
lu.adicionar(5);
lu.adicionar(20);
lu.adicionar(5);
lu.adicionar(35);
lu.adicionar(35);
lu.adicionar(15);
lu.adicionar(10);
lu.adicionar(35);
lu.setDuplicatas(false);
lu.ordena();
System.out.println("Ordenado: " + lu);


Ordenado: 5, 10, 15, 20, 35
Out[7]:
null

Sobrescrevendo Métodos

  • Método na subclasse sobrescreve o da superclasse quando tem a mesma assinatura
    • para um objeto da subclasse, o método da subclasse (que sobrescreve) será chamado no lugar daquele da superclasse
    • não afeta objetos declarados na superclasse
  • Assinatura do método
    • composta do nome do método mais os tipos dos argumentos, considerando a ordem

Sobrescrevendo Métodos de Alguem

  • Considera a hierarquia de classes
    • Melissa e Alcebiades sobrescrevem o método getNome de Alguem

In [8]:
public class Alguem {
    public String getNome() {
       return "alguem (genericamente)";
    }
}


Out[8]:
com.twosigma.beaker.javash.bkr16b44ab1.Alguem

In [9]:
public class Alcebiades extends Alguem {
    public String getNome() {
       return "Alcebiades";
    }
}


Out[9]:
com.twosigma.beaker.javash.bkr16b44ab1.Alcebiades

In [10]:
public class Melissa extends Alguem {
    public String getNome() {
       return "Melissa";
    }
}


Out[10]:
com.twosigma.beaker.javash.bkr16b44ab1.Melissa

Tarefa

Veja o código a seguir e descreva o que ele deve fornecer como saída (faça isso sem executá-lo):

Alguem a = new Alguem();
Alcebiades b = new Alcebiades();
Melissa c = new Melissa();

System.out.println("Nome a: " + a.getNome());
System.out.println("Nome b: " + b.getNome());
System.out.println("Nome c: " + c.getNome());

In [ ]:

Referência à Superclasse: super

  • Referência explícita à superclasse
  • Só é necessária quando há sobrescrita de método
  • Uso comum: método da classe herdeira sobrescreve um método da superclasse mas quer estendê-lo
  • A cláusula super representa a superclasse:
    super.metodo()
    

Estendendo Métodos

  • Método adicionar de ListaEstatica sobrescreve o mesmo método de Lista
  • Objetivo: estender o método adicionar para guardar maior valor em cada adição
  • Chamada de método da superclasse com a cláusula super
    • Se não fosse usado o super faria uma chamada recursiva

In [11]:
public class ListaEstatistica extends Lista {
   private int maiorValor = 0;

   public void adicionar(int item) {
      super.adicionar(item);
      maiorValor = (item > maiorValor) ? item : maiorValor;
   }
   
   public double soma() {
      double s = 0;
      for (int l = 0; l <= ultimo; l++)
         s += vlista[l];
      return s;
   }
   
   public double media() {
      return (ultimo >= 0)
            ? soma() / (ultimo+1) : 0;
   }

   public int maior() {
      return maiorValor;
   }
}


Out[11]:
com.twosigma.beaker.javash.bkr16b44ab1.ListaEstatistica

Mostrando o maior valor


In [12]:
ListaEstatistica le = new ListaEstatistica();
le.adicionar(10);
le.adicionar(20);
le.adicionar(5);
le.adicionar(35);
le.adicionar(15);
System.out.println("Soma: " + le.soma());
System.out.println("Media: " + le.media());
System.out.println("Maior: " + le.maior());


Soma: 85.0
Media: 17.0
Maior: 35
Out[12]:
null

Construtor da Superclasse - super

  • Chamando o construtor da superclasse:
    • apenas a cláusula super na forma de método, com parâmetros (se houver):
      super()
      
  • Só pode ser chamado do construtor da classe
  • Se for chamado, tem que ser a primeira instrução do construtor

Acrescentando um construtor com tamanho para Lista


In [13]:
public class Lista {
   protected int vlista[];
   protected int ultimo = -1;
   
   public Lista(int tamanho) {
      vlista = new int[tamanho];
   }
   
   public void adicionar(int item) {
      if (ultimo+1 < vlista.length) {
         ultimo++;
         vlista[ultimo] = item;
      }
   }
   
   public String toString() {
      String str = "";
      for (int l = 0; l <= ultimo; l++)
         str += vlista[l] + ((l < ultimo) ? ", " : "");
      return str;
   }
}


Out[13]:
com.twosigma.beaker.javash.bkr16b44ab1.Lista

Estendendo o construtor

  • ListaUtil estende o construtor acrescentando o controle de duplicatas

In [14]:
public class ListaUtil extends Lista {
   private boolean duplicatas = true;
   
   public ListaUtil(int tamanho, boolean duplicatas) {
      super(tamanho);
      this.duplicatas = duplicatas;
   }
   
   public boolean getDuplicatas() {
      return duplicatas;
   }
   
   public void setDuplicatas(boolean duplicatas) {
      this.duplicatas = duplicatas;
   }

   public void ordena() {
      int lastSwap = ultimo;
      while (lastSwap > 0) {
         int swap = 0;
         for (int v = 0; v < lastSwap; v++)
            if (vlista[v] > vlista[v+1]) {
               int aux = vlista[v];
               vlista[v] = vlista[v+1];
               vlista[v+1] = aux;
               swap = v;
            }
          lastSwap = swap;
      }
      
      if (!duplicatas) {
         int s = 0;
         for (int v = 0; v <= ultimo; v++)
            if (vlista[s] != vlista[v]) {
               s++;
               vlista[s] = vlista[v];
            }
         ultimo = s;
      }
   }

}


Out[14]:
com.twosigma.beaker.javash.bkr16b44ab1.ListaUtil

Construtor sem argumentos implícito e Herdeiros

  • O construtor sem argumentos é implícito (não precisa ser declarado)
  • Quando uma classe declara somente construtor com argumentos:
    • o construtor sem argumentos deixa de existir
    • subclasses deixam de ter construtor implícito e precisam declará-lo

Ajustando classe ListaEstatistica

  • ListaEstatistica é obrigada a declarar construtor explícito
  • Repassa chamada para superclasse

In [15]:
public class ListaEstatistica extends Lista {
   private int maiorValor = 0;
   
   ListaEstatistica(int tamanho) {
      super(tamanho);
   }

   public void adicionar(int item) {
      super.adicionar(item);
      maiorValor = (item > maiorValor) ? item : maiorValor;
   }
   
   public double soma() {
      double s = 0;
      for (int l = 0; l <= ultimo; l++)
         s += vlista[l];
      return s;
   }
   
   public double media() {
      return (ultimo >= 0)
            ? soma() / (ultimo+1) : 0;
   }

   public int maior() {
      return maiorValor;
   }
}


Out[15]:
com.twosigma.beaker.javash.bkr16b44ab1.ListaEstatistica

Usando novos construtores


In [16]:
ListaUtil lu = new ListaUtil(10, false);
lu.adicionar(10);
lu.adicionar(5);
lu.adicionar(20);
lu.adicionar(5);
lu.adicionar(35);
lu.adicionar(35);
lu.adicionar(15);
lu.adicionar(10);
lu.adicionar(35);
lu.ordena();
System.out.println("Ordenado: " + lu);

ListaEstatistica le = new ListaEstatistica(5);
le.adicionar(10);
le.adicionar(20);
le.adicionar(5);
le.adicionar(35);
le.adicionar(15);
System.out.println("Soma: " + le.soma());
System.out.println("Media: " + le.media());
System.out.println("Maior: " + le.maior());


Ordenado: 5, 10, 15, 20, 35
Soma: 85.0
Media: 17.0
Maior: 35
Out[16]:
null

Tarefa

Escreva uma classe ListaOpera herdeira de ListaEstatistica que acrescente um método multiplica() para multiplicar todos os itens da lista por um valor.

No construtor, deve ser informado um parâmetro fator que indicará o fator de multiplicação. Este fator é guardado em atributo e será usado quando método multiplica() que não recebe parâmetros.


In [ ]: