if669 - Introdução à Programação
Aula 4
Igor Ebrahim (ies)
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;
Cliente
Métodos
Atributos
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
Variáveis
Métodos
public
private
Viola o
encapsulamento
Força o
encapsulamento
Oferece serviços
aos clientes
Dá suport a
outros métodos
da classe
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
interface é palavra reservada
Nenhum dos métodos
de uma interface
possuem uma definição
public interface Factivel
{
public void facaIsto();
public int facaIsto();
public void facaIsto2 (float valor, char ch);
public boolean facaOutro (int num);
}
Um ponto-e-vírgula termina
cada 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;
Interfaces
public class Faz implements Factivel
{
public void facaIsto ()
implements é palavra
{
reservada de Java
// qualquer coisa
}
public int facaIsto ()
{
// qualquer coisa
}
// etc.
}
Cada método listado
em 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 superclasse, 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 subclasse é uma versão mais específica que a superclasse;’
Forma
FormaBidimensional
Circulo
Quadrado
Triângulo
FormaTridimensional
Esfera
Cubo
Tetraedro
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 subclasses;
• 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 subclasses – 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 superclasse) 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
Feriado dia;
dia = new Natal();
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 referese:
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”);
ClassCastException na
2ª iteração
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.”);
}
Genéricos
Date hoje = new Date();
List lista = new ArrayList();
lista.add(hoje);
lista.add(“10/12/2005”);
Sem Exception, mas
com erro de lógica
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.”);
}
Genéricos
Date hoje = new Date();
List<Date> lista = new ArrayList<Date>();
lista.add(hoje);
lista.add(“10/12/2005”);
Erro de compilação
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.”);
}
Métodos Genéricos
•
Considere
três métodos
sobrecarregados
essese char visto
Usamos Integer,
Double printArray
e Character
ao invés de int,
double
métodos
imprimem
de ser
string
dos elementos
de
que somento
tipos as
porrepresentações
referência podem
utilizados
com métodos
e
um array de Integers, um array
de Doubles
e um array de
classes
genéricas!
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 + “ ”);
}
Métodos Genéricos
•
Agora, repare no método printArray genérico:
Muito menos código, não?!
Seção de parâmetro
de tipo
Cada seção de parâmetro de tipo pode conter
um ou mais parâmetros de tipo separados por
vírgulas.
public <E> void printArray( E[] inputArray ) {
for ( E element : inputArray )
System.out.print(element + “ ”);
}
É recomendado que parâmetros de tipos sejam
especificados como letras maiúsculas
individuais.
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;
}
}
Argumentos de
tipo
...
Registro<String, Integer> registro =
new Registro<String, Integer>(“um”, new
Integer(1));
...
Limite Inferior
public class Registro<K,V extends Number>{
private K chave;
private V valor;
Com classe ou
interface usamos a
Registro(K chave,V valor){
palavra reservada
this.chave = chave;
extends
this.valor = valor;
}
}
//OK
Registro<String, Double> registro =
new Registro<String, Double
>(“um”,new Double(1.0));
//Erro de compilação
Registro<String, Endereco> registro =
new Registro<String, Endereco
>(“um”,new Endereco());
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();
//OK
listaInteiros.add(new Integer(2));
listaInteiros.add(new String(“2”));
//Erro execução
Integer i = (Integer)listaInteiros.get(1);
Genéricos e Coleções
• Com genéricos:
ArrayList<Integer> listaInteiros =
new ArrayList <Integer>();
//OK
listaInteiros.add(new Integer(2));
//Erro de compilação
listaInteiros.add(new String(“2”));
//Não precisa de cast
Integer 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;
Tipo desconhecido
public double sum ( ArrayList< ? extends Number > list ) {
double total = 0;
for ( Number element : list )
total = total + element.doubleValue();
return total;
}
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.
Download

public