Aula 4 Igor Ebrahim (ies) if669 - Introdução à Programação Monitoria de IP.

Post on 21-Apr-2015

105 views 2 download

Transcript of Aula 4 Igor Ebrahim (ies) if669 - Introdução à Programação Monitoria de IP.

Aula 4Aula 4

Igor Ebrahim (ies)

if669 - Introdução à Programação

Monitoria de IP

Agenda

• Encapsulamento• Conversão de Tipos• Interfaces• Herança• Polimorfismo• Genéricos

Encapsulamento

• Visões de objetos:– Interna - atributos e métodos da classe que o define;

– Externa - os serviços que um objeto proporciona e como ele interage com o resto do sistema;

• Externamente, um objeto é uma entidade encapsulada;

• Um objeto pode usar os serviços providos por outro – mas não deve saber como estes serviços são implementados;

• Qualquer mudança no estado de algum atributo do objeto usado deve ser feito através de seus métodos – dificultar (tornar impossível) a mudança direta de atributos fora da própria classe;

Encapsulamento

• Pode-se pensar no objeto encapsulamento como sendo uma caixa preta;

Métodos

Atributos

Cliente

Modificadores de Acesso

• Java torna possível o encapsulamento através dos modificadores de acesso;

• Um modificador é uma palavra reservada que especifica uma característica particular de um método ou atributo;

• Java possui três modificadores de acesso: public, protected e private;

Modificadores de Acesso

• Membros que são declarados como:– public podem ser referenciados em qualquer parte;– private só podem ser referenciados dentro da própria

classe;

• Membros que são declarados sem modificadores de acesso têm visibilidade default e podem ser referenciados por qualquer classe do mesmo pacote;

Modificadores de Acesso

public private

Variáveis

Métodos Oferece serviçosaos clientes

Dá suport a outros métodos

da classe

Força oencapsulamento

Viola o encapsulamento

Modificadores de Acesso

• Por possuir atributos privados, a classe geralmente oferece serviços através de seus métodos para que se acessar e alterar seus valores.

• Esses métodos são conhecidos como Getters e Setters.

• Exemplo:– Se tivermos o atributo private int altura.– O método de acesso será: public int getAltura().– O método para mudança será:

public void setAltura(int altura).

Modificadores de Acesso

• O uso desta prática dá ao programador o direito de restringir a forma como um atributo pode ser mudado;

• Por exemplo:– Imagine uma classe Dado que possui o atributo:

private int face;– Uma face de um dado não tem que estar entre 1 e 6,

então, o método setFace ficaria assim:

public void setFace(int face) {

if (face >= 1 && face <=6)

this.face = face;

}

Conversão de Tipos

• Pode ser conveniente converter um tipo de dado para outro;

• Por exemplo, em uma situação particular podemos querer tratar um inteiro como um ponto flutuante;

• Essas conversões não mudam o tipo da variável ou o valor armazenado, elas apenas convertem o valor como parte da computação;

Conversão de Tipos

• Conversões devem ser feitas com cuidado para evitar perda de informação;

• Conversão Ampliada são mais seguras porque elas tendem a ir de um tipo “menor” para um “maior”;

• Conversão Reduzida podem perder informação porque vão de um tipo “maior” para um “menor”;

• Em Java, conversão de dado pode ocorrer de três tipos:– Conversão atribuída;– Promoção;– Casting.

Conversão Atribuída

• Conversão atribuída ocorre quando um valor de um tipo é atribuído a uma variável de outro tipo;

float f;

int i;

i = 2;

f = 2;• Apenas conversões ampliadas podem ser feitas

dessa maneira;• Note que o valor e o tipo de i não mudam;

Promoção

• Promoção ocorre automaticamente quando operadores em uma expressão convertem seus operandos;

• Por exemplo, se soma for um float e o cont for um int:

result = sum / cont;• O valor de cont é convertido para ponto flutuante

para realizar o cálculo;

Casting

• Casting é a mais poderosa, porém perigosa, técnica de conversão;

• Tanto conversão ampliada e reduzida podem ser feitas;

• O tipo é posto entre parênteses em frente ao valor a ser convertido;

• Por exemplo, se total e cont forem inteiros:

result = (float) total / cont;• O valor de result será um ponto flutuante;

Interfaces

• Uma interface em Java é uma coleção de métodos abstratos e constantes;

• Um método abstrato é um cabeçalho de método sem o seu corpo;

• Um método abstrato pode ser declarado usando o modificador abstract, mas como todos os métodos de uma interface são abstratos, normalmente não usa-se o modificador;

• Uma interface é usada para estabelecer um conjunto de métodos que uma classe irá implementar;

Interfaces

public interface Factivel{ public void facaIsto(); public int facaIsto(); public void facaIsto2 (float valor, char ch); public boolean facaOutro (int num);}

interface é palavra reservadaNenhum dos métodos

de uma interfacepossuem uma definição

Um ponto-e-vírgula terminacada um dos cabeçalhos

dos métodos

Interfaces

• Uma interface não pode ser instanciada;• Métodos em uma interface têm que ser public

“por default”;• Uma classe implementa uma interface:

– Declarando isto no cabeçalho da classe;– Implementando cada um dos métodos abstratos da

interface.

• Uma classe que implementa uma interface deve definir TODOS os métodos da interface;

Interfacespublic class Faz implements Factivel{ public void facaIsto () { // qualquer coisa }

public int facaIsto () { // qualquer coisa }

// etc.}

implements é palavrareservada de Java

Cada método listadoem Factivel recebe

uma definição

Interfaces

• Uma classe que implementa uma interface pode definir outros métodos também;

• Além de métodos abstratos, interfaces podem conter constantes;

• Quando uma classe implementa uma interface, ela ganha acesso a todas essas constantes.

Interfaces

• Uma classe pode implementar múltiplas interfaces;• As interfaces são listadas após o implements;• A classe deve implementar todos os métodos de

todas as interfaces listadas.

class MuitasCoisas implements interface1, interface2

{

// todos os métodos de ambas as interfaces

}

Interfaces

• A biblioteca padrão de Java contem uma série de interfaces úteis;

• A interface Comparable contém um método abstrato chamado compareTo, que é usado para comparar dois objetos;

• A classe String implementa Comparable, dando a ela a habilidade de colocar strings em ordem lexicográfica;

Olhem a API de Java para mais detalhes...

Dêem uma olhada em na interface Iterator. Qualque dúvida procurem seus monitores.

Herança

• Técnica de programação orientada a objetos usada para organizar e criar classes para reuso;

• Possibilita derivar uma classe de outra já existente;

• A classe existente é chamada de super-classe ou classe base;

• A classe derivada é chamada de sub-classe;• A sub-classe herda as características da super-

classe, ou seja, a sub-classe herda os métodos e os atributos definidos pela super-classe;

Herança

• A herança cria uma relação “é um”, isto é, a sub-classe é uma versão mais específica que a super-classe;’

Forma

FormaBidimensional FormaTridimensional

TriânguloQuadradoCirculo TetraedroCuboEsfera

Herança

• O programador pode implementar uma classe derivada como for preciso, adicionando novos atributos ou métodos, ou até mesmo, modificando os herdados;

• Reuso de software é uma vantagem no uso de herança;

Criando Sub-classes

• Em Java, usa-se a palavra reservada extends para estabelecer uma relação de herança:

class FormaBidimensional extends Forma

{

// conteúdo da classe

}

Modificadores de Acesso

• Modificadores de acesso afetam a maneira como atributos e métodos podem ser usadas nas sub-classes;

• Atributos e métodos declarados privados (private) não podem ser referenciados diretamente em sub-classes;

• Atributos e métodos declarados públicos (public) podem ser referenciados diretamente em sub-classes – mas atributos públicos ferem o princípio do encapsulamento;

Modificadores de Acesso

• O modificador protected permite à sub-classe referenciar uma variável ou métodos da classe herdada diretamente;

• Isso oferece um maior encapsulamento do que o uso do public, mas não tanto quanto o private;

• Um atributo (ou método) protected é visível a qualquer classe dentro do mesmo pacote da super-classe;

super

• Construtores não são herdados, mesmo que sejam public;

• Ainda assim, geralmente precisamos usar o contrutor da super-classe para inicializar a parte herdada;

• A referência super pode ser usada para referenciar a classe herdada ou para invocar o seu construtor.

super

• O construtor da sub-classe é responsável por chamar o construtor da super-classe;

• A primeira linha do construtor da sub-classe deve conter a referência super para chamar o construtor da super-classe;

• A referência super também pode ser usada para referenciar outros atributos ou métodos definidos na super-classe.

Herança Múltipla

• Java suporta herança simples, ou seja, uma classe pode herdar apenas de uma outra classe;

• Múltipla herança permite a uma classe herdar de várias outras classes;

• Colisões, como duas super-classes terem o mesmo nome de um atributo, têm que ser resolvidas;

• Java não suporta herança múltipla.

Overriding Métodos

• Uma sub-classe pode sobrescrever (override) a definição de um método herdado;

• O novo método tem que possuir a mesma assinatura do método herdado, mas pode ter um corpo completamente diferente;

• O tipo do objeto que executa o método é que determina qual das versões é realmente invocada;

• Se um método for definido na super-classe com o modificador de acesso final, ele não pode ser sobrescrito;

Overloading vs. Overriding

• Overloading (sobrecarregar) múltiplos métodos com o mesmo nome e na mesma classe, mas com assinaturas diferentes;

• Overriding (sobrescrever) métodos em classes diferentes (um na sub-classe e outro na super-classe) que possuem a mesma assinatura;

• Overloading permite ao programador definir operações semelhantes, mas de diferentes formas e para parâmetros diferentes;

• Overriding permite ao programador definir operações semelhantes, mas de diferentes formas e para diferentes tipos de objetos.

A Classe Object

• A classe Object é definida no pacote java.lang da biblioteca básica de Java;

• Todas as classes são derivadas da classe Object;

• Se uma classe não é explicitamente definida como filha de uma outra classe já existente, Java assume que ela é filha direta de Object;

A Classe Object

• A classe Object possui alguns métodos que podem ser úteis, que são herdados por todas as classes;

• Por exemplo, o método toString é definido em Object;

• Toda vez que definimos o método toString, nós estamos sobrescrevendo o método herdado;

• O método toString na classe Object é definido para retornar uma String que contém o nome da classe do objeto, além de outras informações;

A Classe Object

• O método equals da classe Object retorna true se duas referências forem “aliases”;

• Podemos sobrescrever o equals em qualquer classe para definir a igualdade de uma melhor maneira;

• Para verificar a igualdade entre duas String´s, devemos usar o método equals;

• Os programadores da classe String sobrescreveram o método equals herdado de Object em favor de seu melhor uso.

Classes Abstratas

• Uma classe abstrata é uma classe que representa uma idéia (conceito) genérica;

• Uma classe abstrata não pode ser instanciada;• Usa-se o modificador abstract no cabeçalho da

classe para declará-la como uma classe abstrata:

public abstract class Produto

{

// conteúdo

}

Classes Abstratas

• Uma classe abstrata geralmente contém métodos abstratos (sem definição);

• Ao contrário das interfaces, o modificador abstract tem que ser aplicado a todos os métodos abstratos;

• As classes abstratas também podem possuir métodos não abstratos;

• As classes abstratas não precisam necessariamente possuir métodos abstratos.

Classes Abstratas

• Uma sub-classe de uma classe abstrata tem que sobrescrever seus métodos abstratos ou eles continuarão sendo considerados abstratos;

• Um método abstrato não pode ser definido como final ou static;

Herança para Interfaces

• Herança também pode ser aplicada a interfaces da mesma forma que nas classes;

• Isto é, uma interface pode derivar de uma outra já criada;

• A interface filha herda todos os métodos abstratos da interface herdada;

• A classe que implementar a interface filha deve definir todos os métodos;

Herança

• Uma relação de herança bem feita pode contribuir bastante com a elegância, a manutenção e o reuso do software;

• Toda herança pode ser uma relação “é um”;• Pense sempre adiante, na potencialidade de uma

classe ser herdada.;• Encontre características comuns entre as classes

e empurre-as para cima na hierarquia;• Sobrescreva métodos apropriadamente;• Adicione novos atributos nas sub-classes, mas

não redefina os herdados;

Herança

• Permita que cada classe gerencie seu próprio conteúdo; use o super para chamar o construtor da classe herdada;

• Use classes abstratas para representar conceitos gerais;

• Use os modificadores de acesso com cuidado para não violar o encapsulamento;

Polimorfismo

• Polimorfismo é um conceito de orientação objeto que nos permite criar versáteis designs de softwares

Binding (Ligação)

• Considere a seguinte chamada de método:

obj.facaIsto();• Em algum ponto, essa chamada é ligada à

definição do método;• Em Java, esta ligação é feita dinamicamente, ou

seja, em tempo de compilação;• Por isto chamamos de dynamic binding (ligação

dinâmica)

Polimorfismo

• O termo polimorfismo significa “muitas formas”;• Uma referência polimórfica é uma variável que

pode se referir a diferentes tipos de objetos em diferentes instantes;

• Um método invocado através de uma referência polimórfica pode mudar de chamada para chamada;

• Todas as chamadas de método em Java são potencialmente polimórfica;

Polimorfismo

• Suponha que criamos a seguinte variável:

Emprego emp;• Java permite a esta referência apontar a um objeto

Emprego ou a qualquer outro objeto de tipo compatível;

• Essa compatibilidade pode ser estabelecida usando herança ou interfaces;

• Um uso cuidadoso de polimorfismo pode gerar elegantes e robustos softwares;

Referências e Herança

• Uma referência para um objeto pode apontar para um objeto de sua própria classe ou para um objeto relacionado a ele por herança;

• Por exemplo, se a classe Feriado é usada para derivar a classe Natal, então uma referência de Feriado pode apontar para um objeto Natal:

Feriado dia;dia = new Natal();

Feriado

Natal

Polimorfismo via Herança

• É o tipo do objeto que está sendo referenciado, não o tipo da referência, que determina qual método é chamado;

• Suponha que o classe Feriado tenha um método chamado celebrar, e que a classe Natal sobrescreve-a;

• Agora, considere a seguinte chamada:

dia.celebrar();• Se dia refere-se a um objeto Feriado, então

invoca-se a versão de celebrar de Feriado; Se dia refere-se a um objeto Natal, ele chama a versão de Natal

Polimorfismo via Interfaces

• Um nome de uma interface pode ser usada como tipo de uma referência de uma variável de objeto:

Speaker atual;• A referência atual pode ser usada para apontar

para qualquer objeto de qualquer classe que implemente a interface Speaker;

• A versão do método speak que a seguinte linha chama depende do tipo de objeto que atual refere-se:

atual.speak();

Polimorfismo via Interfaces

• Suponha que duas classes, Filosofo e Cao, ambas implementam a interface Speaker, fornecendo versões distintas do método speak;

• Analisemos o seguinte código:

Speaker s = new Filosofo();

s.speak();

s = new Dog();

s.speak();

Verificação Dinâmica de Tipo

• Podemos usar Casting ou o operador instanceof para fazer verificação de tipo:

• Cast:

Conta conta;

conta = new Poupanca("21.342-7");

...

((Poupanca) conta).renderJuros(0.01);

conta.imprimirSaldo();

Verificação Dinâmica de Tipo

• instanceof:

Conta c = this.procurar("123.45-8");

if (c instanceof Poupanca)

((Poupanca) c).renderJuros(0.01);

else

System.out.print("Poupança inexistente!“)

• Casts geram exceções quando instanceof retorna false;

• Casts são essenciais para verificação estática de tipos (compilação);

Genéricos

• Recurso novo do J2SE 5.0 (Tiger);

Genéricos

• Métodos e classes genéricas estão entre as capacidades mais poderosas de Java para reutilização de software com segurança de tipo em tempo de compilação;

• Ou seja:– Maior facilidade de desenvolvimento;– Maior robustez:

• Cria classes type-safe;

• Evita o uso extensivo de type casts e instanceof.

• Métodos/classes genéricas permitem que, com uma única declaração de método/classe, o programador especifique um conjunto de métodos/classes;

Genéricos

Date hoje = new Date();List lista = new ArrayList();lista.add(hoje);lista.add(“10/12/2005”);

public void imprimirListaData(List datas){Iterator i = datas.iterator();while(i.hasNext()){

Date data = (Date)i.next();System.out.println(data);

} System.out.println(“A lista tem ” + datas.size() + “ datas.”);

}

ClassCastException na 2ª iteração

GenéricosDate hoje = new Date();List lista = new ArrayList();lista.add(hoje);lista.add(“10/12/2005”);

public void imprimirListaData(List datas){Iterator i = datas.iterator();while(i.hasNext()){

Object o = i.next();if(o instanceof Date){

Date data = (Date)o;System.out.println(data);

}}System.out.println(“A lista tem ” + datas.size() +

“ datas.”);}

Sem Exception, mas com erro de lógica

GenéricosDate hoje = new Date();List<Date> lista = new ArrayList<Date>();lista.add(hoje);lista.add(“10/12/2005”);

public void imprimirListaData(List<Date> datas){Iterator<Date> i = datas.iterator();while(i.hasNext()){

Date data = i.next();System.out.println(data);

} System.out.println(“A lista tem ” + datas.size() + “ datas.”);

}

Erro de compilação

Métodos Genéricos

• Considere três métodos printArray sobrecarregados esses métodos imprimem as representações de string dos elementos de um array de Integers, um array de Doubles e um array de Characters, respectivamente:

public void printArray( Integer[] inputArray) {for (Integer element : inputArray)

System.out.print(element + “ ”);}

public void printArray( Double[] inputArray) {for (Double element : inputArray)

System.out.print(element + “ ”);}

public void printArray( Character[] inputArray) {for (Character element : inputArray)

System.out.print(element + “ ”);}

Usamos Integer, Double e Character ao invés de int, double e char visto que somento tipos por referência podem ser utilizados com métodos e

classes genéricas!

Métodos Genéricos

• Agora, repare no método printArray genérico:

public <E> void printArray( E[] inputArray ) {for ( E element : inputArray )

System.out.print(element + “ ”);}

Muito menos código, não?!

Seção de parâmetro de tipo

É recomendado que parâmetros de tipos sejam especificados como letras maiúsculas

individuais.

Cada seção de parâmetro de tipo pode conter um ou mais parâmetros de tipo separados por

vírgulas.

Classe Genérica (ou Parametrizada)

public class Registro<K,V>{

private K chave;private V valor;

Registro(K chave,V valor){this.chave = chave;this.valor = valor;

}

}

...Registro<String, Integer> registro =

new Registro<String, Integer>(“um”, new Integer(1));

...

Argumentos detipo

Limite Inferiorpublic class Registro<K,V extends Number>{

private K chave;private V valor;

Registro(K chave,V valor){this.chave = chave;this.valor = valor;

}}//OKRegistro<String, Double> registro =

new Registro<String, Double >(“um”,new Double(1.0));

//Erro de compilaçãoRegistro<String, Endereco> registro =

new Registro<String, Endereco >(“um”,new Endereco());

Com classe ou interface usamos a palavra reservada

extends

Genéricos e Coleções

• Genéricos são muito utilizados com coleções;• Por exemplo, até o Java 1.4, um ArrayList era uma

coleção de Object, mesmo que durante a execução, instâncias de vários tipos pudessem estar associados a ele:

ArrayList listaInteiros = new ArrayList();//OKlistaInteiros.add(new Integer(2)); listaInteiros.add(new String(“2”));

//Erro execuçãoInteger i = (Integer)listaInteiros.get(1);

Genéricos e Coleções

• Com genéricos:

ArrayList<Integer> listaInteiros =new ArrayList <Integer>();

//OKlistaInteiros.add(new Integer(2));//Erro de compilaçãolistaInteiros.add(new String(“2”));

//Não precisa de castInteger i = listaInteiros.get(0);

Genéricos e Coleções

• Usando o novo for:

ArrayList<Integer> listaInteiros = new ArrayList <Integer>();

listaInteiros.add(new Integer(1));listaInteiros.add(new Integer(2));

for(Integer i:listaInteiros ){out.println(i);

}

Curinga

• Suponha que você queira implementar um método genérico sum que some os número sem uma coleção, como o ArrayList;

• Queremos ser capazes de somar todos os números na ArrayList independente dos seus tipos;

public double sum( ArrayList< Number > list ) {

double total = 0;

for ( Number element : list )

total = total + element.doubleValue();

return total;

}Será que esse método funcionaria se passássemos como parâmetro um

ArrayList< Integer > ?

Curinga

• Ao compilar o programa, o compilador emitiria a seguinte mensagem de erro:sum(java.util.ArrayList<java.lang.Number>) in

NomeDaClasse cannot be applied to (java.util.ArrayList<java.lang.Integer>)

• Embora Number seja superclasse de Integer, ArrayList<Number> não é superclasse de ArrayList<Integer>;

• Como criar uma versão mais flexível? Usando os argumentos de tipo curinga;

Curinga

• Os curingas permitem especificar parâmetros de método, valores de retorno, variáveis ou campos etc., que atuam como supertipos de tipos parametrizados;

public double sum ( ArrayList< ? extends Number > list ) {double total = 0;

for ( Number element : list )total = total + element.doubleValue();

return total;}

Tipo desconhecido

Utilizar um curinga na seção de parâmetros de tipo de um método ou utilizar um curinga como um tipo explícito de uma variável no corpo do método é

um erro de sintaxe.

Genéricos e Type Safety

• O javac (compilador de Java) 5.0 reclamará caso encontre alguma ação insegura quanto ao tipo:

List list = new ArrayList();list.add("teste");

• Por exemplo, na segunda linha irá aparecer um warning:

“Type safety: The method add(Object) belongs to the raw type List. References to generic type List<E>

should be parameterized”• Como tirar o warning?!

Genéricos e Herança

• Uma classe genérica pode ser derivada de uma classe não-genérica; Por exemplo, a classe Object é uma superclasse direta ou indireta de cada classe genérica;

• Uma classe genérica pode ser derivada de outra classe genérica; Por exemplo, a classe Stack (no pacote java.util) é uma subclasse da classe genérica Vector (no pacote java.util);

Genéricos e Herança

• Uma classe não-genérica pode ser derivada de uma classe genérica; Por exemplo, a classe Properties (no pacote java.util) é uma subclasse da classe genérica Hashtable (no pacote java.util);

• Um método genérico em uma subclasse pode sobrescrever um método genérico em uma superclasse se os dois métodos possuírem a mesma assinatura.