Esta é uma pré-visualização de arquivo. Entre para ver o arquivo original
1 Unidade V Unidade V –– HeranHerançça e a e LigaLigaçção Dinâmicaão Dinâmica Linguagem de ProgramaLinguagem de Programaçção Ião I Universidade Federal da Paraíba Centro de Ciências Exatas e da Natureza Departamento de Informática Daniela Coelho Batista Guedes Pereira © 2 Unidade V Conteúdo abordado: Herança Ligação Dinâmica e Polimorfismo Classes Abstratas 3 Herança A Herança é a contribuição original do paradigma de programação orientado a objetos Fundamentos chave do paradigma OO: Abstração de Dados Herança Ligação Dinâmica A herança é um relacionamento entre classes Relacionamento do tipo é um Classes são derivadas de outras classes, portanto herdam atributos e métodos dessas classes. 4 Herança 5 Herança Forma de reutilização de código Propriedades e métodos são herdados, evitando sua duplicação em várias classes similares Forma de generalização/especialização de tipos Várias classes podem ser generalizadas em uma classe que concentre todas as características comuns a todas elas Uma classe pode ser especializada em várias outras classes Pelo menos duas classes participam da herança 6 Herança Papéis das classes que participam da herança: Superclasse: classe a partir da qual são herdadas as propriedades e métodos Subclasse: classe que herda as propriedades e métodos da superclasse Se uma classe herda de outra, então: Os objetos da subclasse possuem todas as propriedades de instância declaradas na superclasse Pode-se enviar para um objeto da subclasse uma mensagem cuja implementação esteja na superclasse 2 7 Herança Exemplos de relacionamentos de herança no mundo real: Um carro é um veículo Um gerente é um funcionário Um homem é um mamífero Um mamífero é um animal Na POO a herança não é um relacionamento entre objetos, mas entre as classes destes objetos No mundo real, a herança algumas vezes é uma relação entre seres (o filho herda dos pais) 8 Herança Definindo herança na UML: Quadrado -lado: int +draw() Triangulo -base: int -altura:int +draw() Circulo -raio: int +draw() Figura -pos: Ponto +setPos() Especialização Generalização 9 Herança Declaração de herança em Java: public class Figura { private Ponto pos; public void setPos(Ponto p) { ... } } public class Figura { private Ponto pos; public void setPos(Ponto p) { ... } } public class Quadrado extends Figura { private int lado; public void draw() { ... } } public class Quadrado extends Figura { private int lado; public void draw() { ... } } palavra reservada de Java 10 Herança Declaração de herança em C++: class Figura { private: Ponto pos; public: void setPos(Ponto p) { ... } } class Figura { private: Ponto pos; public: void setPos(Ponto p) { ... } } class Quadrado:Figura { private: int lado; public: void draw() { ... } } class Quadrado:Figura { private: int lado; public: void draw() { ... } } 11 Herança Declaração de herança em Smalltalk: classname Figura superclass Object instance variable names |pos| setPos: p "Implementação de setPos" classname Figura superclass Object instance variable names |pos| setPos: p "Implementação de setPos" classname Quadrado superclass Figura instance variable names |lado| draw "Implementação de draw" classname Quadrado superclass Figura instance variable names |lado| draw "Implementação de draw" 12 Herança Efeito da herança sobre os objetos da subclasse: Figura f = new Figura(); Quadrado q = new Quadrado(); Figura f = new Figura(); Quadrado q = new Quadrado(); pos f q lado pos f.setPos(new Ponto(10,20)); q.setPos(new Ponto(30,40)); q.draw(); f.setPos(new Ponto(10,20)); q.setPos(new Ponto(30,40)); q.draw(); Operações perfeitamente válidas 3 13 Herança Herdando o estado: Todos os objetos da subclasse terão uma cópia das variáveis de instância declaradas em todas as suas superclasses Herdando o comportamento: Todos os métodos de instância da superclasse também são métodos dos objetos das suas subclasses Construtores não são herdados pelas subclasses, mas o construtor da superclasse tem que ser invocado na subclasse implicitamente (através do construtor default) ou explicitamente (através da clausula super). Ao enviar uma mensagem para um objeto da subclasse, a busca por um método começa na subclasse e se estende pelas superclasses 14 Herança public class Bicycle { //a classe Bicycle tem três campos private int cadence; private int gear; private int speed; //a classe Bicycle tem um construtor public Bicycle(int startCadence,int startSpeed,int startGear){ gear = startGear; cadence = startCadence; speed = startSpeed; } //a classe Bicycle tem quatro métodos public void setCadence(int newValue) { cadence = newValue; } public void setGear(int newValue) { gear = newValue; } public void applyBrake(int decrement) { speed -= decrement; } public void speedUp(int increment) { speed += increment; } } 15 Herança public class MountainBike extends Bicycle { //a subclasse MountainBike adiciona um campo private int seatHeight; //a subclasse MountainBike tem um construtor public MountainBike(int startHeight, int startCadence,int startSpeed,int startGear){ super(startCadence, startSpeed, startGear); seatHeight = startHeight; } //a subclasse MountainBike adiciona um método public void setHeight(int newValue) {seatHeight = newValue; } } 16 Herança Níveis de acesso a membros de uma classe: O acesso package ou friendly é obtido quando não se especifica nenhum dos outros três modificadores de controle de acesso. Classe Subclasse Pacote Outros private public protected package 17 Herança em Java Observe que: O encapsulamento private não impede que uma propriedade ou método seja herdado; entretanto, o acesso a estes membros é impedido na subclasse O nível de acesso protected permite que membros sejam invisíveis a outras classes, mas sejam visíveis às subclasses e às classes do mesmo pacote Java possui uma classe Object que é a raiz da árvore de classes da linguagem (não tem superclasse) Java só permite herança simples (apenas uma superclasse) 18 Herança Sobrescrita de métodos Se uma subclasse implementa um método de instância que já exista na superclasse dizemos que houve uma sobrescrita de método (override) Os métodos devem possuir a mesma assinatura A busca pelo método inicia-se e termina na subclasse O método sobrescrito pode chamar o método original da superclasse na sua implementação: super • Neste caso, se a visibilidade o permitir Não confunda esse conceito com sobrecarga 4 19 Herança Sobrescrita de métodos Se uma subclasse implementa um método de classe que já exista na superclasse dizemos que houve uma ocultação do método da superclasse (hiding) 20 Herança: overhiding X hiding public class Animal { public static void testClassMethod() { System.out.println(“Método de classe em Animal."); } public void testInstanceMethod() { System.out.println(“Método de instância em Animal."); } } public class Cat extends Animal { public static void testClassMethod() { System.out.println(“Método de classe em Cat."); } public void testInstanceMethod() { System.out.println(“Método de instância em Cat."); } public static void main(String[] args) { Cat myCat = new Cat(); Animal myAnimal = myCat; Animal.testClassMethod(); Cat.testClassMethod(); myAnimal.testInstanceMethod(); } } Método de classe em Animal. Método de classe em Cat. Método de instância em Cat. 21 Herança Exemplo de sobrescrita: Venda -data: Date +getData(): Date +addProduto(Produto) +getTotal(): real Produto -preço: real -descriçao: String +getValor() +setValor(double) 0..n VendaPrazo -juros: int +getTotal() VendaVista -desconto: int +getTotal() 22 Herança Implementação de Venda em Java public class Venda { private Produto produtos[]; private int numProdutos; private Date data; //Calcula o total bruto da conta public double getTotal() { double total = 0.0; for (int i=0; i<numProdutos ;i++) { total += produtos[i].getPreco(); } return total; } } public class Venda { private Produto produtos[]; private int numProdutos; private Date data; //Calcula o total bruto da conta public double getTotal() { double total = 0.0; for (int i=0; i<numProdutos ;i++) { total += produtos[i].getPreco(); } return total; } } 23 Herança Implementação de VendaPrazo em Java: A referência super aponta para o objeto corrente, mas faz a busca pelo método getTotal() começar na superclasse de VendaPrazo Sem o super, a chamada seria recursiva! public class VendaPrazo extends Venda { private int juros; public double getTotal() { return super.getTotal()*(1+juros/100.0); } } public class VendaPrazo extends Venda { private int juros; public double getTotal() { return super.getTotal()*(1+juros/100.0); } } 24 Ligação Dinâmica Uma mensagem só é ligada a um método em tempo de execução ligação dinâmica Na ligação estática, a ligação entre a chamada de um subprograma e sua implementação é estabelecida em tempo de compilação Com a herança, não se sabe exatamente qual o método a ser invocado até que se conheça o tipo real do objeto (tipo dinâmico). Durante a compilação só temos o tipo das referências (tipo estático) 5 25 Ligação Dinâmica Considere o seguinte código: public class Caixa { private Venda vendas[]; private int numVendas; //Calcula o total do caixa public double getTotal() { double total = 0.0; for (int i=0; i<numVendas ;i++) { total += vendas[i].getTotal(); } return total; } } public class Caixa { private Venda vendas[]; private int numVendas; //Calcula o total do caixa public double getTotal() { double total = 0.0; for (int i=0; i<numVendas ;i++) { total += vendas[i].getTotal(); } return total; } } 26 Venda[ ] Ligação Dinâmica Ilustração de um objeto Caixa: vendas desconto juros juros desconto Caixa VendaVista VendaPrazo VendaVista VendaPrazo caixa 27 Ligação Dinâmica Observe o código do getTotal() de Caixa: public class Caixa { public double getTotal() { double total = 0.0; for (int i=0; i<numVendas ;i++) { total += vendas[i].getTotal(); } return total; } } public class Caixa { public double getTotal() { double total = 0.0; for (int i=0; i<numVendas ;i++) { total += vendas[i].getTotal(); } return total; } } VendaPrazo -juros: int +getTotal() VendaVista -desconto: int +getTotal() Qual getTotal() será chamado aqui? 28 Ligação Dinâmica A ligação entre a mensagem vendas[i].getTotal() e o método getTotal() de uma das classes só é estabelecida em tempo de execução, quando o tipo do objeto em vendas[i] for conhecido Venda é o tipo de cada referência do arranjo vendas VendaVista e VendaPrazo serão os tipos efetivos dos objetos referenciados pelo arranjo Exemplo: Venda v = new VendaVista(); tipo estático tipo dinâmico 29 Polimorfismo Polimorfismo Do Grego poly(muitas) + morpho(formas) Há dois aspectos do polimorfismo Métodos de mesmo nome são definidos em várias classes, podendo assumir diferentes implementações em cada uma dessas Propriedade pela qual uma variável pode apontar objetos de diferentes classes em momentos distintos Estes aspectos são complementares, e trabalham juntos 30 Polimorfismo Exemplo do polimorfismo em métodos: Triangulo area();area(); Retangulo Hexagono area(); Poligono area(); 6 31 Polimorfismo Exemplo de polimorfismo em variáveis: Uma variável do tipo Poligono pode assumir a forma de Poligono, Triangulo, Retangulo, etc. Poligono p; p = new Poligono(); ... p = new Triangulo(); ... p = new Retangulo(); Poligono p; p = new Poligono(); ... p = new Triangulo(); ... p = new Retangulo(); 32 Exemplo de uso de Polimorfismo Área de um arranjo de polígonos: double areaTotal() { double areaTotal = 0; for (int i = 0; i < MAXPOLIG; ++i) { if (pol[i] instanceof Poligono) areaTotal += pol[i].areaPoligono(); else if (pol[i] instanceof Triangulo) areaTotal += pol[i].areaTriangulo(); double areaTotal() { double areaTotal = 0; for (int i = 0; i < MAXPOLIG; ++i) { if (pol[i] instanceof Poligono) areaTotal += pol[i].areaPoligono(); else if (pol[i] instanceof Triangulo) areaTotal += pol[i].areaTriangulo(); continua 33 Exemplo de uso de Polimorfismo Área total sem polimorfismo: else if (pol[i] instanceof Retangulo) areaTotal += pol[i].areaRetangulo(); else if (pol[i] instanceof Hexagono) areaTotal += pol[i].areaHexagono(); return areaTotal; } else if (pol[i] instanceof Retangulo) areaTotal += pol[i].areaRetangulo(); else if (pol[i] instanceof Hexagono) areaTotal += pol[i].areaHexagono(); return areaTotal; } 34 Exemplo de uso de Polimorfismo Área total com polimorfismo Rápido, enxuto e fácil de entender O acréscimo de uma nova subclasse de Poligono não altera nenhuma linha do código acima! double areaTotal() { double areaTotal = 0; for (int i = 0; i < MAXPOLIG; ++I) areaTotal += poligono[i].area(); return areaTotal; } double areaTotal() { double areaTotal = 0; for (int i = 0; i < MAXPOLIG; ++I) areaTotal += poligono[i].area(); return areaTotal; } 35 Benefícios do polimorfismo Legibilidade do código O mesmo nome para a mesma operação (método) facilita o aprendizado e melhora a legibilidade Código de menor tamanho Código mais claro, enxuto e elegante. Flexibilidade Pode-se incluir novas classes sem alterar o código que a manipulará O polimorfismo é implementado com o uso da ligação dinâmica 36 Classes abstratas Pode-se implementar classes que definem comportamentos “genéricos” A essência da superclasse é definida e pode ser parcialmente implementada Detalhes são definidos em subclasses especializadas Em geral, não podem ser instanciadas Em Java: Declara-se a classe com abstract 7 37 Classes abstratas Conta String num; double saldo; credito(); debito(); saldo(){..} getNum(){..} Poupanca double taxa; credito(){..} debito(){..} rendeJuros(){..} ContaEspecial int limite; credito(){..} debito(){..} ContaBonus int bonus; credito(){..} debito(){..} 38 Classes abstratas Quando declarar uma classe abstract? Quando a classe representar um conceito abstrato e não fizer sentido instanciá-la Quando a classe for apenas um ponto de concentração para propriedades e métodos comuns a várias subclasses Quando a classe possuir pelo menos um método abstrato, deve ser obrigatoriamente abstrata Classes abstratas reforçam uma decisão de projeto 39 Classes abstratas ContaEspecial Poupanca ContaBonus Conta 40 Classes abstratas Exemplo: public abstract class Conta { private String num; private double saldo; } public abstract class Conta { private String num; private double saldo; } public class Poupanca extends Conta { //... } public class Poupanca extends Conta { //... } public class ContaEspecial extends Conta { //... } public class ContaEspecial extends Conta { //... } Não produz instâncias 41 Classes abstratas Método abstrato: Método definido numa classe abstrata e sem implementação Sintaxe e semântica: O método é identificado com a palavra abstract Apenas a assinatura é declarada na classe abstrata Todas as subclasses concretas devem implementá-lo obrigatoriamente Usado para forçar as subclasses a terem um determinado comportamento 42 Classes abstratas Exemplo de métodos abstratos: public abstract class Figura { public abstract void desenha(); public abstract double area(); } public abstract class Figura { public abstract void desenha(); public abstract double area(); } public class Quadrado extends Figura { public void desenha() {...} public double area() {...} } public class Quadrado extends Figura { public void desenha() {...} public double area() {...} } 8 43 Classes e métodos finais em Java Uma classe pode ser final em Java Não pode possuir subclasses Razões para definir classes finais: Segurança da aplicação (definição de classes imutáveis) Decisão de projeto Um método pode ser final também Não pode ser sobrescrito nas subclasses O corpo do método é substituído em todos os pontos de uso (chamadas inline) Métodos private são implicitamente final 44 Classes e métodos finais em Java Uso de final em métodos: class Exemplo { private int a; public final void setA(int a) { this.a = a; } } class Teste { private static void metodoTeste(Exemplo ex) { ex.setA(5); } } 45 Classes e métodos finais em Java Uso de final em métodos: class Exemplo { private int a; public final void setA(int a) { this.a = a; } } class Teste { private static void metodoTeste(Exemplo ex) { ex.a = 5; } } O compilador otimiza o código nas chamadas a métodos final