Orientação a Objetos e a Linguagem Java Afrânio Assis afranio@gmail.com Novembro/2006 1
Reutilizição com Herança e Composição Novembro/2006 2
Introdução Separar as partes que podem mudar das partes que provavelmente não mudam Programador cliente: deve poder usar o código sem a preocupação de ter que reescrever seu código caso surjam versões futuras Programador de biblioteca: deve ter a liberdade de fazer melhoramentos sabendo que o cliente não terá que modificar seu código Deve-se esconder do cliente Métodos que não fazem parte da interface Todos os atributos de dados Novembro/2006 3
Reutilização A reutilização de código leva a produtos melhores e mais lucrativos O código reusado já foi testado Não é necessário reinventar a roda a cada nova aplicação, esse reuso de código implica em redução de gastos Podemos reutilizar classes utilizando dois mecanismos da orientação a objetos: Composição Herança Novembro/2006 4
Composição Ocorre quando uma classe X possui um atributo cujo o tipo é definido por uma classe Y, ou seja, há uma associação entre as duas classes, sendo Y parte do todo X. Ex: A classe Carro possui como atributos um Motor e quatro Pneus, sendo o Motor e os Pneus partes do Carro. Um objeto da classe X terá uma referência para um objeto da classe Y Novembro/2006 5
Composição public class Carro { private Motor motor; private Pneu[] pneus class Motor { class Pneu { Carro Motor Pneu Novembro/2006 6
Herança É um mecanismo para derivar novas classes a partir de classes existentes Subclasses (mais específicas) herdam todos os atributos e métodos (não privados) das superclasses (mais gerais) Métodos herdados podem ser sobrescritos, além disso novos métodos e atributos podem ser criados nas subclasses super(... ) deve ser a primeira instrução do construtor. Caso não seja especificado, é usado o construtor padrão Ex: Quadrado herda de Quadrilatero Novembro/2006 7
Herança Mamífero comer() Object Animal peso locomover() Ave locomover() voar() Réptil locomover() nadar() Caso não exista a cláusula extends, então, assume-se que a superclasse é Object. Em Java, Object é a superclasse de todas as classes peso é uma propriedade que está presente em todos os objetos criados para as classes Animal, Mamífero, Ave e Réptil Ave pardal = new Ave(); pardal.peso = 700; Mamifero boi = new Mamifero() boi.peso = 8000; boi.locomover(); Novembro/2006 8
Composição x Herança Composição Queremos características de uma classe existente dentro de nossa classe, mas não queremos sua interface Relação parte de entre classes Herança Queremos reusar a interface de uma classe já existente relação é um entre classes Novembro/2006 9
Exemplo de Composição public class Ponto { private int x, y; public Ponto() { setponto(0,0); public Ponto(int a, int b) { setponto(a,b); public void setponto(int a, int b) { x = a; y = b; public int getx() { return x; public int gety() { return y; public String tostring() { return "[" + x + ", " + y + "]"; Novembro/2006 10
Exemplo de Composição import java.lang.math; public class Circulo { private Ponto p; private double raio; public Circulo() { p = new Ponto(0,0); setraio(0); public Circulo(double r, int a, int b) { p = new Ponto(a,b); setraio(r); public void setraio(double r) { raio = r; public double getraio() { return raio; Novembro/2006 11
Exemplo de Composição public double getarea() { return Math.PI * raio * raio; public void setponto(int a, int b) { p.setponto(a,b); // O usuário não tem acesso ao centro do círculo public int getx() { return p.getx(); public int gety() { return p.gety(); public String tostring() { return "Centro = " + p.tostring() + "; Raio = " + raio; Novembro/2006 12
Exemplo de Herança import java.lang.math; public class Circulo extends Ponto { private double raio; public Circulo( ) { super(0, 0); setraio(0); public Circulo( double r, int a, int b) { super (a, b); setraio( r ); public void setraio( double r ) { raio = r; Novembro/2006 13
Exemplo de Herança public double getraio( ) { return raio; public double getarea( ) { return Math.PI * raio * raio; public String tostring() { return "Centro = " + super.tostring + "; Raio = " + raio; Novembro/2006 14
Composição x Herança Composição - Benefícios Permite que um objeto seja composto de vários outros objetos Podemos fazer alterações em tempo de execução Ex: podemos trocar os Pneus de um objeto do tipo Carro durante a execução do programa Herança - Restrições Um classe herda diretamente APENAS DE UMA outra classe A herança apenas pode ser alterada durante a edição do programa Novembro/2006 15
Composição x Herança Composição e herança não são mutuamente exclusivas As técnicas podem ser usadas em conjunto para obter os melhores resultados de cada uma Novembro/2006 16
Sobrescrita e Ocultação Sobrescrita (overriding): substituir a implementação de um método da superclasse, mantendo a assinatura. Não confundir sobrescrita com sobrecarga Ocultação (shadowing): declarar variáveis membros com os mesmos identificadores usados na superclasse. Novembro/2006 17
Sobrescrita Métodos sobrescritos nunca podem ter menos acesso que os métodos originais Se o método original for public, novas versões têm que ser public Se o método original for protected, novas versões só podem ser protected ou public Se método original for private, ele não será visível fora da classe e, portanto, não poderá ser sobrescrito Até pode ser criado um método na classe filha com a mesma assinatura de um método private na classe mãe, mas isso não é sobrescrita. Métodos de classe (static) nunca são sobrescritos Novembro/2006 18
Novembro/2006 19
Upcasting e Downcasting Permissão de subtipos se passarem por supertipos: Figura f = new Circulo(); Círculo é uma Figura Sempre seguro: Círculo é um conjunto extendido de Figura A operação inversa, denominada downcasting, é perigosa: Circulo c = (Circulo) f; Nem toda Figura é um Circulo Novembro/2006 20
Inicialização e Carga de Classe Uma classe precisa ser carregada na memória quando utilizada pela primeira vez: primeiro objeto construído acesso a um membro estático necessidade da superclasse Ordem de inicialização: membros estáticos em ordem textual (uma única vez) inicialização de campos Novembro/2006 21
class Insect { int i = 9; int j; Insect() { prt("i = " + i + ", j = " + j); j = 39; static int x1 = prt("static Insect.x1 initialized"); static int prt(string s) { System.out.println(s); return 47; public class Beetle extends Insect { int k = prt("beetle.k initialized"); Beetle() { prt("k = " + k); prt("j = " + j); static int x2 = prt("static Beetle.x2 initialized"); Novembro/2006 22
public static void main(string[] args) { prt("class load"); Beetle b = new Beetle(); //Saída: //static Insect.x1 initialized //static Beetle.x2 initialized //Class load //i = 9, j = 0 //Beetle.k initialized //k = 47 //j = 39 //Se o main fosse apenas: new Beetle(); //static Insect.x1 initialized //static Beetle.x2 initialized //i = 9, j = 0 //Beetle.k initialized //k = 47 //j = 39 Novembro/2006 23
Inicialização e Carga de Classe Inicialização procura pelo método estático Beetle.main() para carregar a classe Beetle (Beetle.class) precisa antes carregar Insect inicialização estática em Insect inicialização estática da subclasse Beetle imprime Class load chamada do construtor da superclasse Insect variáveis do objeto inicializadas (ordem textual) construtor de Insect executado retorna ao construtor de Beetle variáveis do objeto inicializadas (ordem textual) construtor de Beetle executado Novembro/2006 24