Prévia do material em texto
marcelo@ifpb.edu.br
3
MEU FILHO
SE PARECE
COMIGO!
UM DIA TUDO DO
MEU PAI VAI SER
MEU!
• Consiste em derivar novas classes a partir de outras já
existentes
– Reusabilidade de código
– Parcial ou Total
• Baseia-se no conceito de herança do mundo real
– Características de uma geração (pai ou mãe) podem ser
passadas aos mais novos (filhos)
• É considerado um dos pilares da programação
orientada a objetos
4
• Entre as classes que participam de um relacionamento
onde há herança temos a seguinte situação:
5
subclasse
superclasse
filha
(classe derivada)
estende (é um(a))
pai
(classe base)
Notação
UML
• Quando uma classe estende outra, significa que
ela é uma especialização de outra, ou seja um
tipo específico
6
pessoa
aluno
é uma
mamífero
cachorro
é um generalização
especialização
• A API Java está organizada de forma hierárquica:
7
Object
Component
Window
Container
• Podemos obter um conjunto de classes distintas a
partir de uma única
8
animal
mamífero ave réptil
é um
9
animal
mamífero ave réptil
é um
cobra lagarto
é um
Hierarquia de
Classes
...
• Quando uma classe estende outra, ela recebe os
campos (variáveis e constantes) e as operações
(métodos)
• Deve-se respeitar as condições de acessibilidade
de cada classe, assim como de seus campos e
métodos
10
11
Caminhão
carga total
abrir compart. de carga
fechar compart. de carga
Automóvel
número de pneus
potência
tipo de combustível
andar
freiar
buzinar
atributos: número de pneus,
potência, tipo de combustível,
carga total
operações: andar,
freiar, buzinar, abrir
e fechar.
12
class Automovel {
int numPneus,tipoComb;
double pot;
public void andar(){...};
public void freiar(){...};
public void buzinar() {...};
}
class Caminhao extends Automovel {
double cargatotal;
public boolean abrir( ){ }
public boolean fechar( ){ }
}
• A subclasse, quando necessário, deverá utilizar o
construtor da superclasse para inicializar os
atributos herdados
• A chamada ao construtor da superclasse é feita
através da palavra chave super
13
14
class Automovel {
int numPneus,tipoComb;
double pot;
public Automovel(int numPneus,int tipoComb,double pot){
this.numPneus = numPneus;
this.tipoComb = tipoComb;
this.pot = pot
}
...
}
15
class Caminhao extends Automovel {
double cargatotal;
public Caminhao(int numPneus,int tipoComb,double
pot,double tc){
super(numPneus,tipoComb,pot);
this.cargatotal = cargaTotal;
}
}
16
Automóvel
Caminhão new Caminhao(numPneus, tipoComb,pot,cargaTotal)
super(numPneus,tipoComb,pot)
this.cargaTotal = cargaTotal
• Uma classe pode ter alguma operação que foi
herdada do pai mas que tem uma
implementação diferente:
• Exemplo: um carro esporte pode ter uma forma
de freiar diferente da forma típica de um
automóvel.
17
18
automóvel
numpneus
pot
tipocomb
andar
freiar
buzinar
caminhão
cargatotal
abrir
fechar
carro esporte
freiar
Reuso parcial Reuso total
NOVO!
• Se não queremos que uma classe seja estendida
devemos utilizar o modificador final:
19
final class Automovel {
int numpneus,tipocomb;
double pot;
public void andar( ) { ... };
public void freiar( ) { ... };
public void buzinar( ) { ... };
}
• Se não queremos que um método seja
sobreposto devemos utilizar o modificador final:
20
class Automovel {
int numpneus,tipocomb;
double pot;
public final void andar() { ... };
public final void freiar() { ... };
public final void buzinar() { ... };
}
• O acesso aos membros da classe pai depende do
tipo de acesso concedido:
– public: acessível a todas as classes, mesmo estando
fora do pacote
– private: inacessível a todas, exceto a própria classe
– protected: acessível às subclasses e as classes do
próprio pacote
– default: acessível a todas as classes do mesmo pacote
21
22
Automóvel
Caminhão
public int numPneus
private int tipoComb
protected double pot
public int numPneus
protected double pot
?
23 PAI DESPREOCUPADO
AINDA BEM QUE
POSSO TER UM
POUCO DE
PRIVACIDADE....
Senha do
Banco...
Senha do
CARTÃO DE
CRÉDITO...
24
class Main {
Triangulo triangulo = new Triangulo();
...
public void setTriangulo(Triangulo novoTriangulo){
Triangulo fig = novoTriangulo;
}
}
setTriangulo
:triangulo Apenas instancias da
classe Triangulo podem
entrar em setTriangulo
25
class Main {
public static void main(String[] args){
Main m = new Main();
System.out.println(“escolha...”);
int tipo = scan.nextInt();
switch(tipo){
case 1: m.setFigura(new Circulo());
break;
case 2: m.setFigura(new Quadrado());
break;
}
}
public void setFigura(Figura NovaFig){
Triangulo t = (Triangulo) novaFig;
…
}
}
setFigura
:Quadrado :Circulo
:Figura
:Figura
:Circulo :Quadrado ??? Instancias de qualquer classe
que estenda Figura podem
entrar em setFigura
• Uma classe é abstrata quando pelo menos um
de seus métodos não é implementado...
• Nesse caso, a implementação fica por conta
das subclasses
• Isso é bastante comum quando um
determinado comportamento é genérico
demais...
– Exemplo: o método andar da classe mamífero
27
28
public abstract class Mamifero {
public abstract void andar( );
// Outros métodos
}
• A palavra chave abstract designa uma classe
classe como sendo abstrata
• O método sem implementação também deve ser
designado com a palavra abstract
29
public abstract class Mamifero {
public abstract void andar( );
// Outros métodos
}
• Uma classe abstrata não pode ser instanciada
– tem que estendê-la e concretizá-la para poder
realizar a instanciação
• Uma classe abstrata pode ser estendida
– a classe filha recebe todos os métodos passíveis de
herança (inclusive os abstratos) e, portanto, passa a
ser abstrata também
30
31
public abstract class cachorro extends Mamifero{
public abstract void andar( );
}
mamífero
cachorro
extends
Podemos ter cachorros que andam de forma
diferente: reais (o seu cachorro!) e
imaginários (o Snoopy anda em pé!)
Por isso, deixaremos o método andar sem
Implementação...
andar()
andar()
• A idéia por trás do polimorfismo é que para uma
mesma mensagem, objetos diferentes se
comportem de forma diferente (poli = várias;
morfo = forma)
32
andar()
carro
mamífero
???
• Não é preciso saber a priori quais os objetos
especificamente iremos lidar, mas apenas
genericamente
– Via classes abstratas ou interfaces (falaremos disso mais
tarde!)
• A descoberta de quem vai responder à mensagem
(chamada do método) ocorrerá em tempo de execução
– Ligação Dinâmica (Dinamic Binding)
33
34
Figura
Círculo Triângulo Quadrado
é um
area( ) area( ) area( )
area( )
Muito genérico!
abstract class Figura {
private String cor;
public abstract double area( );
}
• Classe Quadrado
35
class Quadrado extends Figura {
private double b, alt;
public Quadrado(double b, double alt){
this.b = b;
this.alt = alt;
}
public double area(){return b*alt; }
}
• Classe Círculo
36
class Circulo extends Figura {static final double PI = 3.14;
private double r;
public Circulo (double r){
this.r = r;
}
public double area( ) {
return r*r*PI;
}
}
• Classe Triângulo
37
class Triangulo extends Figura {
private double b;
private double alt;
public Triangulo(double b, double alt){
this.b = b;
this.alt = alt;
}
public double area() { return b*alt/2; }
}
38
public class Teste {
public static void main(String[] args){
Figura[] fig = new Figura[3];
fig[0] = new Quadrado(1,2);
fig[1] = new Circulo(2);
fig[2] = new Triangulo(2,3);
for(int i=0; i < 3; i++){
System.out.println(fig[i].area());
}
}
}
• Uma interface é uma classe que possui todos os
métodos abstratos e/ou declarações de
constantes
– Não têm variáveis
– Não têm construtores
– Não têm métodos implementados
– Podem ter constantes
40
• “Programar para a Interface, não para a
implementação”
– Maior flexibilidade
– Implementações mudam, conceitos ficam
– Programar para o futuro e não para o presente
41
• Grau de Abstração
42
Classe Concreta
atributos
constantes
métodos concretos
Classe Abstrata
atributos
constantes
métodos concretos
métodos abstratos
Interfaces
constantes
métodos abstratos
• Uma interface é declarada da seguinte forma:
43
interface Operavel {
static final int MAX = 10;
public int soma(int a, int b);
public int subtrai(int a, int b);
public int multiplica(int a, int b);
public int divide(int a, int b);
}
Método(s) abstratos(s)
Constante(s)
• Uma interface não deve ser instanciada, ela deve
ser implementada:
44
public class calculadora implements Operavel{
public int soma(int a,int b){return a+b;}
public int subtrai(int a,int b){return a-b;}
public int mult(int a,int b){return a*b;}
public int divide(int a, int b) {return a/b;}
}
• Podemos implementar mais de uma interface
45
Calculadora
Operavel Representavel *-avel
implements
46
class calculadora implements Operavel,Representavel{
// métodos de Operavel
public int soma(int a, int b){return a + b;}
public int subtrai(int a, int b){return a - b;}
public int multiplica(int a, int b){return a*b;}
public int divide(int a, int b){return a / b;}
// método de Representavel
public void exibeNaTela(int valor){
System.out.println(“O valor é ” + valor);
}
}
• Um dos problemas da orientação a objetos é lidar
com a necessidade de estender mais de uma
classe ao mesmo tempo:
47
? ?
soma( )
A
soma( )
B
C
?
• A solução em Java é implementar métodos de
uma interface e estender métodos de outra
48
Calculadora
Representável Verificadora
implements implements extends
Interfaces Classe
Operável
• Permite estender uma classe sem fazer herança
49
class calculadora extends Verificadora implements
Operavel,Representavel {
// métodos de Operavel
public int soma(int a, int b){return a+b;}
public int subtrai(int a, int b){return a-b;}
public int multiplica(int a, int b){return a*b;}
public int divide(int a, int b){return a/b;}
// método de Representavel
public void exibeNaTela(int valor){
System.out.println(“O valor é ” + valor);
}
}
• Se todos os métodos da Interface não forem
implementados, a classe será abstrata
50
Calculadora
Operavel
public int soma(int a, int b){ return a + b; }
CalculadoraCientifica
implements
extends public abstratct int subtrai(int a, int b){
return a – b;
}
Interface
Classe Abstrata
Classe Concreta
public abstratct int soma(int a, int b);
public abstract int subtrai(int a, int b);
public abstract int subtrai(int a, int b);
51
interface Operavel{
public int soma(int a, int b);
public int subtrai(int a, int b);
public int mult(int a, int b){return a*b;}
public int div(int a, int b){return a/b;}
}
abstract class Calculadora implements Operavel{
public int soma(int a, int b){
return a + b;
}
}
52
class CalcCient extends Calculadora {
public int subtrai(int a, int b){
return a-b;
}
public int multiplica(int a,int b){
return a*b;
}
public int divide(int a, int b){
return a/b;
}
}
• A linguagem Java contém inúmeras interfaces em
sua API:
– java.util.Observer
– java.lang.Cloneable
– java.io.Serializable
– Java.util.zip.Checksum
53
• Semelhante ao Polimorfismo com Classes
Abstratas:
– Os elementos aptos a executar uma determinada
operação polimórfica deve implementar a Interface
que define o Polimorfismo
54
55
public interface Comparavel {
public boolean comparaCom(Object o);
}
56
public class Livro implements Comparavel {
private double preço;
public Livro(double preço){
this.preço = preço;
}
public void setPreço(double novoPreço){
preço = novoPreço;
}
public double getPreço(){
return preço;
}
public boolean comparaCom(Object o){
if (o instanceof Livro){
Livro l = (Livro) o;
if (this.getPreco() > l.getPreco())
return true;
}
return false;
}
}
57
public class Teste {
public static void main(String[] args){
Teste meuTeste = new Teste();
Comparavel[] arrayComp = new Comparavel[3];
arrayComp[0] = new Livro(50.00);
arrayComp[1] = new Livro(3000.00);
arrayComp[2] = new Livro(0.80);
System.out.println(“Antes...”);
for(int i=0; i < 3; i++){
System.out.println(arrayComp[i].getPreço());
}
meuTeste.ordenar(arrayComp);
58
System.out.println(“Depois...”);
for(int i=0; i < 3; i++){
System.out.println(arrayComp[i].toString());
}
} // main
// Continua no próximo slide.
59
public void ordenar(Comparavel[ ] c){
int tam = c.length;
Comparavel aux;
for(int i=0; i < tam - 1; i++){
for(int j=1; j < tam; j++){
if(c[i].comparaCom(c[j])){
aux = c[j];
c[j] = c[i];
c[i] = aux;
}
}
}
} // fim de ordenar
} // fim da classe
• Upcast
– Uma superclasse ou entidade genérica (classe
abstrata ou interface) pode receber sempre uma
subclasse ou entidade específica (classe
implementadora)
60
Figura minhaFigura = new Triangulo(...);
teste.insere(new Triangulo(2,3));
public void insere(Figura f) { /* código */ }
61
Caminhão
peso total de carga
abrir compart. de carga ()
fechar compart. de carga ()
Automóvel
número de pneus
potência
tipoCombustível
andar ()
freiar ()
buzinar ()
Automovel auto = new Caminhao(...);
auto
auto.andar()
auto.freiar()
auto.buzinar()
OK!
auto.abrir()
auto.fechar()
NÃO!
• Downcast
– Uma superclasse ou entidade genérica (classe
abstrata ou interface) deve ser convertida
explicitamente para o tipo da subclasse ou entidade
específica (classe implementadora)
62
public boolean comparaCom(Object o){
Livro l = (Livro) o;
if (this.getAno() < l.getAno())
return true;
return false;
}
• Downcast
– Se a referência em “o” não for um Livro teremos um
problema!
63
Object
Automóvel
número de pneus
potência
tipoCombustível
andar ()
freiar ()
buzinar ()
Livro
título
autor
número de páginas
mudarPagina ()
pesquisar (plv)
ClassCastException
Ok!!!
• Downcast
– Antes dese usar uma referência de uma entidade
genérica é importante se testar sua origem:
64
if(o instanceof Livro)
Object
Livro
o Object
Automovel
o
65
Superclasse /
Interface
(Figura)
Subclasse /
Classe Concreta
(Circulo)
Subclasse /
Classe Concreta
(Circulo)
upcasting downcasting
if(aluno1.comparaCom(aluno2)) { ... }
...
public boolean comparaCom(Object o) { ... }
Aluno aux = (Aluno) o;
• Vamos projetar um jogo
no qual será possível, de
acordo com determinadas
condições, mudar o braço
de um robô.
• Cada braço tem uma
funcionalidade
diferente...
• A mudança deve ser feita
de forma transparente
66
67 Robô
Braço com Broca
Braço com Tesoura
? ?
68
public class Robo{
private Cabeça c;
private Perna p;
private Tronco t;
private Braço b;
public Robo(Cabeça c, Perna p, Tronco t, Braço b){
this.c = c;
this.p = p;
this.t = t;
this.b = b;
}
// Outros métodos...
}
69
public class Robo{
// atributos ...
public Robo(Cabeça c, Perna p, Tronco t,
BraçoComTesoura bct){
/* corpo */
}
}
public class Robo{
// atributos ...
public Robo(Cabeça c, Perna p, Tronco t,
BraçoComBroca bcb){
/* corpo */
}
}
OU
70
<<interface>>
Braço
BraçoComGarra BraçoComBroca BraçoComArma
implements
atacar()
atacar( ) atacar( ) atacar( )
71
public interface Braço{
public void atacar();
}
public class BraçoComGarra implements Braço {
/* Corpo da Classe */
}
public class BraçoComBroca implements Braço {
/* Corpo da Classe */
}
public class BraçoComArma implements Braço {
/* Corpo da Classe */
}
72
public class Robo{
private Cabeça c;
private Perna p;
private Tronco t;
private Braço b;
public Robo(Cabeça c, Perna p, Tronco t, Braço b){
/* código */
}
...
}
73
public class Robo{
private Cabeça c;
private Perna p;
private Tronco t;
private Braço b;
public Robo(Cabeça c, Perna p, Tronco t, Braço b){
/* código */
}
...
}
Qual é o tipo do
braço do robô?
O que mudou
nessa classe?
74
public class RobotGame{
public static void main(String[] args){
Braço b1 = new BraçoComGarra();
Braço b2 = new BraçoComBroca();
Braço b3 = new BraçoComArma();
/* Criação de c1 e t1 omitida */
Robo r1 = new Robo(c1,t1,b1);
Robo r2 = new Robo(c1,t1,b2);
Robo r3 = new Robo(c1,t1,b3);
/* Restante do Código */
r1.setBraco(b2);
}
Mesmo construtor,
Diferentes Robôs
• O tipo de braço do robô pode ser conhecido em
Compile Time (estaticamente) ou Run Time
(Dinamicamente)
– A classe Robo é projetada sem levar em
consideração o tipo de braço que será usado (o
mesmo poderia ser feito para as demais partes)
75
76
• O Polimorfismo libera a classe cliente do tipo específico
de comportamento que ela deve usar
Braço
abre()
<<Interface>>
Robô
BraçoComBroca
abre( )
BraçoComArma
abre( )
77
• Existem mecanismos bastante eficientes para o
desenvolvimento de software flexível e
reutilizável:
Padrões de Projeto: 23
estratégias para se
abordar o desenvolvimento
de software de forma
madura
78
Escreva um programa em Java que implemente um Sistema de Controle de Folha de
Pagamento Simplificado de uma empresa, composta de diversos funcionários, os
quais podem ser horistas ou comissionados. Todos os funcionários, independente de
categoria, devem ter os atributos “nome”, “matrícula” e “salário”. Os horistas têm
como atributo o “número de horas trabalhadas” (o valor de uma hora trabalhada é
30 reais) e os comissionados o “salário base” e o “total de suas vendas” durante o
mês multiplicado por um “fator de comissão” (cujo valor é 2%). Um comissionado
vende até três produtos diferentes. Um produto tem um “nome”, um “código” e um
“preço” e existem dois tipos: “perecível” ou “não perecível” (o funcionário
comissionado tanto vende produtos perecíveis como não perecíveis) . Um produto
perecível tem uma “data de validade” e um não perecível tem um “prazo de
garantia”. (I) O sistema deve ser capaz de cadastrar funcionários e produtos e
informar o estado atual do funcionário que recebe o maior salário na empresa.
79
Funcionário
nome
matricula
salário
Horista Comissionado
nome
matricula
salário
quantHoras
nome
matricula
salário
salarioBase
totalVendas
80
Funcionário
nome
matricula
salário
Horista Comissionado
nome
matricula
salário
quantHoras
nome
matricula
salário
salarioBase
totalVendas
81
Funcionário
nome
matricula
salário
Horista Comissionado
QuantHoras salarioBase
totalVendas
82
Funcionário
nome
matricula
salário
Horista Comissionado
QuantHoras salarioBase totalVendas
Main
main()
arrayFunc
83
Produto
nome
preço
código
Perecível NãoPerecível
dataVal: Date prazo: Date
Main
main()
arrayFunc
84
Produto
nome
preço
código
Perecível NãoPerecível
dataVal: Date prazo: Date
Horista Comissionado
QuantHoras salarioBase totalVendas
Main
main()
arrayProd
arrayFunc
Funcionário
nome
matricula
salário
vende
3
10
10 tem
tem
• Requisitos Funcionais
– O sistema deve ser capaz de cadastrar funcionários e
produtos
– O sistema deve ser capaz de informar o estado atual
do funcionário com o maior salário
85