• Nenhum resultado encontrado

JavaBasicoHerancaPlus

N/A
N/A
Protected

Academic year: 2021

Share "JavaBasicoHerancaPlus"

Copied!
10
0
0

Texto

(1)

Java Básico

Herança e Polimorfismo

Fábio Gondim

Herança

Herança

• Um dos possíveis mecanismos de reutilização de código / funcionalidade.

• Juntamente com Interfaces são a fonte para o polimorfismo (conforme explicado posteriormente). • Uma nova classe (subclasse) é criada estendendo uma

outra preexistente que passa a ser a sua superclasse.

public class Mamifero extends Animal { //... }

“Mamifero” é uma subclassede “Animal”. “Animal” é uma superclassede “Mamifero”. • As subclasses herdam da superclasse todos os campos e

métodos públicos (public) e protegidos (protected) mesmo que as classes estejam em diferentes pacotes.

Herança

Neste exemplo, simplificado, objetos do tipo Animal (Animal animal;) são capazes de dormir.

Objetos do tipo Mamífero (Mamífero mamifero;) são capazes de dormir e mamar.

Objetos do tipo Cachorro (Cachorro cachorro;) são capazes de dormir, mamar e latir.

Herança

Neste exemplo, simplificado, objetos do tipo Animal(Animal animal;) são capazes de dormir.

Objetos do tipo Mamífero(Mamífero mamifero;) são capazes de dormire mamar.

Objetos do tipo Cachorro(Cachorro cachorro;) são capazes de dormir, mamare latir.

Herança

Um Mamífero é um Mamífero Um Mamífero é um Animal Um Cachorro é um Cachorro Um Cahorro é um Mamífero Um Cachorro é um Animal Um Animal é um Animal

(2)

Herança

Não confunda declaração de tipo com instanciação.

Animal cachorro1 = new Cachorro;

// Para a JVM cachorro1 referencia um Animal. // Apenas as operações de um Animal (e Object) // estarão naturalmente disponíveis.

Mamífero cachorro2 = new Cachorro;

// Para a JVM cachorro2 referencia um Mamífero. // As operações de Mamífero e Animal estarão // naturalmente disponíveis.

Cachorro cachorro3 = new Cachorro;

// Para a JVM cachorro3 referencia um Cachorro. // As operações de Animal, Mamífero e Cachorro // estarão naturalmente disponíveis.

• Campos e métodos sem modificadores de visibilidade (package-private) só serão visíveis pelas subclasses se estiverem dentro do mesmo pacote.

• Campos e métodos privados não são acessíveis pelas subclasses. O acesso aos campos privados podem ocorrer por intermédio de métodos de acesso que sejam visíveis nas subclasses.

• Em UML este relacionamento é chamado de

Generalização. Ao subir na hierarquia caminha-se para a Generalização enquanto que ao descer caminha-se para a Especialização.

Herança

?

?

?

?

?

?

?

?

?

?

?

?

G

e

n

e

ra

li

za

çã

o

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

E

sp

e

ci

a

li

za

çã

o

Exemplo

public classConta {

privateString numero;

private doublesaldo;

privateCliente titular;

publicConta(String numero, doublesaldo, Cliente titular) { //...

}

public voidcreditar(doublevalor) { //...

}

public voiddebitar(doublevalor) throwsSaldoNegativoException { //...

}

public voidtransferir(doublevalor, Conta destino) throws

SaldoNegativoException { //...

} //... }

Suponha uma classe Conta que representa uma conta bancária.

Exemplo

(continuação)

public class Poupanca extends Conta {

public Poupanca(String numero, double saldo, Cliente

titular) {

super(numero, saldo, titular);

}

public void renderJuros(double taxa) {

doublesaldo = this.getSaldo();

this.creditar(saldo * taxa); }

}

Uma conta poupança é muito similar a uma conta corrente normal, mas pode render juros. Solução: faça Poupanca estender Conta e a especialize acrescentando a operação renderJuros(double taxa).

(3)

• Classes declaradas como final não podem ser

estendidas (especializadas).

public final class PostoCombustível { // Esta classe não pode ser estendida // ...

}

Herança

Herança Múltipla



C++

C++

C++

C++

Java

• Ao contrário de C++, Java não suporta herança múltipla: Uma classe qualquer, C, não pode estender ao mesmo tempo duas outras classes quaisquer, A e B.

Herança Múltipla

Java



C++

C++

C++

C++

Obs.: Java permite implementar múltiplas interfaces (assunto visto adiante).

“(...) Herança múltipla é útil quando você quer que uma nova classe combine vários contratos e herde parte de, ou toda a, implementação destes contratos. Mas quando existe mais de uma superclasse, surgem problemas quando um comportamento da superclasse é herdado por dois caminhos. Suponha, por um momento, a seguinte árvore de tipos:

Herança Simples versus Herança Múltipla

“(...) Isto é comumente chamado de herança diamante, e não existe nada de errado com ela. Muitos projetos legítimos mostram esta estrutura. Os problemas existem na herança de implementação, quando a

implementação de W guarda algum estado.

Herança Simples versus Herança Múltipla

Se a classe W tivesse, por exemplo, um campo público denominado goggin, e se você tivesse uma referência a um objeto do tipo Z chamado zref, a que se referiria zref.goggin? Ela poderia se referir à cópia de X de goggin, ou poderia se referir à cópia de Y, ou X e Y poderiam compartilhar uma única cópia de goggin porque Z é na

realidade somente um W mesmo que ele seja também um X e um Y. Resolver tais problemas não é trivial e complicam o projeto e o uso da hierarquia de classes. Para evitar tais questões, a linguagem de programação Java usa o modelo da herança simples da programação orientada a objetos. Herança simples exclui alguns projetos úteis e corretos. Os problemas da herança múltipla surgem da herança múltipla de implementação, mas em muitos casos a herança múltipla é usada para herdar diversos contratos abstratos e talvez uma implementação concreta. Fornecer um meio de herdar um contrato abstrato sem herdar uma implementação permite os benefícios da herança múltipla sem o problema da herança múltipla de implementação. A herança de um contrato abstrato é denominado herança de interface.(...)

[GOSLING et al, 2007, p. 125, 126]

(4)

• Toda classe estende Object, direta ou indiretamente. Por este motivo alguns métodos estão disponíveis em todas as classes: clone(), equals(Object obj), finalize(), getClass(), hashCode(), notify(), notifyAll(), toString(), etc.

Herança - Classe Object

• Há um forte acoplamento entre uma classe e as suas subclasses. Mudanças nas superclasses quase sempre provocam efeitos colaterais em suas subclasses. Cuidado com os chamados efeitos “dominó” ou “gelatina”. • É um relacionamento estático (definido durante o

processo de compilação) e portanto não pode mudar durante a execução do sistema.

• A agregação/composição, explicada posteriormente é um relacionamento dinâmico e portanto mais flexível do que a herança.

• Mais adiante veremos que o uso de interfaces deve ser encorajado.

Herança

• Se a superclasse tem um construtor parametrizado e não possui um construtor padrão (sem parâmetros), as suas subclasses terão que providenciar em seus construtores uma chamada ao construtor parametrizado da superclasse.

Subclasses e construtores

public classPoupanca extendsConta {

publicPoupanca(String numero, doublesaldo, Cliente titular) { super(numero, saldo, titular);

}

public voidrenderJuros(doubletaxa) { doublesaldo = this.getSaldo(); this.creditar(saldo * taxa); }

}

• Toda classe possui pelo menos um construtor. • Um construtor padrão sem parâmetros é incluído

automaticamente pelo compilador sempre que não houver nenhum construtor definido.

• Se um construtor qualquer for especificado, o compilador não incluirá mais nenhum outro.

• Um construtor de uma subclasse deve, obrigatoriamente, invocar o construtor de sua superclasse. Se não houver uma chamada ao construtor da superclasse o compilador incluirá uma chamada para um construtor padrão sem parâmetros por intermédio da instrução super(). Se não existir um construtor padrão na superclasse ocorrerá um erro durante a compilação. O erro desaparecerá se for incluído um construtor padrão na superclasse ou se for inserida, manualmente, uma chamada ao construtor parametrizado da superclasse: super(Tipo1 param1, ...). Esta chamada deve ser a primeira instrução a ser executada.

Subclasses e construtores

Sobrescrita (Override)

public abstract classPassaro { public voidfazerNiho() {

System.out.println(“Fazendo ninho com palha,

gravetos, etc...");

}

// Outros métodos }

A maioria dos

pássaros faz ninhos

assim

Sobrescrita (Override)

Public classJoaoDeBarro extendsPassaro { public voidfazerNiho() {

System.out.println(“Fazendo ninho com argila ...");

}

// Outros métodos }

Mas alguns são

especiais e fogem à

regra

(5)

Sobrescrita (Override)

Public classPinguimextendsPassaro { public voidfazerNiho() {

System.out.println(“Fazendo ninho com pedregulhos ...");

}

// Outros métodos }

Mas alguns são

especiais e fogem à

regra

• Muitas vezes, nem todas as operações definidas em uma superclasse interessam a todas as suas subclasses. Neste caso é necessário que a subclasse que deseja alterar o comportamento sobrescreva o método herdado mantendo a sua assinatura e modificando o seu interior.

Sobrescrita (Override)

public abstract classPassaro { public voidfazerNiho() {

System.out.println(“Fazendo ninho com palha e

gravetos...");

}

// Outros métodos }

public classJoãoDeBarro extendsPassaro { public voidfazerNinho() {

System.out.println(“Fazendo ninho com argila...");

} }

• Ao sobrescrever um método não é permitido reduzir a sua visibilidade. O contrário é permitido, ou seja, pode-se aumentar a visibilidade de um método, mas nunca diminuí-la.

Sobrescrita (Override)

public abstract classPassaro { public voidfazerNiho() {

System.out.println(“Fazendo ninho com palha e

gravetos...");

}

// Outros métodos }

public classJoãoDeBarroextendsPassaro {

protectedvoidfazerNinho() { //ERRO

System.out.println(“Fazendo ninho com argila...");

} }

• Não confunda sobrescrita com sobrecarga. Sobrecarga envolve assinaturas diferentes enquanto que sobrescrita não. Sobrescrita sempre envolve herança enquanto que sobrecarga nem sempre.

Sobrescrita x Sobrecarga

public abstract classPassaro { public voidvoar() {

// implementação }

public voidvoar(doublealtitude) {

// implementação }

public voidvoar(doublealtitude, doublevelocidade) {

// implementação }

}

No exemplo acima voar é um método sobrecarregado.

• Não há sobrecarga e causa um erro de compilação:

– Mudar apenas o tipo de retorno:

Sobrescrita x Sobrecarga

public abstract classPassaro { public voidvoar() {

// implementação }

public doublevoar() {

// implementação } }

Erro:

Método voar()

duplicado

• Não há sobrecarga e causa um erro de compilação:

– Mudar apenas o identificador de um ou mais parâmetros:

Sobrescrita x Sobrecarga

public abstract classPassaro { public voidvoar(doublealtitude) {

// implementação }

public doublevoar(doublealt) {

// implementação }

}

Erro:

(6)

Sobrescrita x Sobrecarga

Sobrescrita Sobrecarga Sobrecarga

Classes Abstratas

• O que você faria se alguém lhe pedisse para

desenhar um animal sem ser específico?

– Perguntaria que animal?

– Escolheria arbitrariamente um animal? – Desenharia um animal imaginário?

– Desenharia um animal composto de partes de vários tipos de animal?

– Desenharia um monstro? – Ficaria paralizado?

Classes Abstratas

Classes Abstratas

Animal animal = new Animal();

// Que Animal???!!!

// Alce? ... Canguru? ... Elefante? ... // Leão? ... Girafa? ... Tartaruga? ...

// Tigre? ... Tubarão? ...

Classes Abstratas

• Algumas classes são importantes para fatorar

comportamento comum, mas não devem gerar instâncias porque são conceitualmente muito abstratas e não possuem elementos suficientes para isoladamente definir objetos.

Animal animal; animal = new Animal();

Classes Abstratas

• “Uma característica extremamente útil da

programação orientada a objetos é o conceito de classe abstrata. Usando classes abstratas você pode declarar classes que definem somente parte de uma implementação, deixando para as classes

estendidas fornecer implementações específicas de alguns ou todos os métodos. O oposto de abstrato é concreto – uma classe que possui somente métodos concretos, incluindo implementações de quaisquer métodos abstratos herdados de superclasses, é uma classe concreta.”

(7)

Classes Abstratas

• Em Java, uma classe abstrata é declarada utilizando-se o modificador abstract antes da palavra class.

public abstract class Animal { //...

}

• Em UML uma classe abstrata tem o seu nome grafado em itálico.

Classes Abstratas

• Uma classe abstrata

não

pode ser instanciada.

Animal animal = new Animal();

public abstract class Animal { //...

}

Classes Abstratas

• Uma classe abstrata pode conter tanto

métodos concretos como métodos abstratos:

public abstract class Animal {

public void dormir() {

// ...

}

public abstract void emitirSom();

// ...

}

Itálico

Classes Abstratas

• Uma classe concreta não pode conter

métodos abstratos.

• Uma classe concreta que estende uma classe

abstrata é obrigada a implementar os

métodos abstratos de sua superclasse

abstrata.

• Uma classe abstrata pode estender uma outra

que seja abstrata. Neste caso é opcional

implementar ou não os métodos abstratos.

Polimorfismo

voar() voar() voar() voar() voar() voar() voar() voar() voar() voar()

• Aonde é esperado um objeto de uma determinada classe pode ser utilizado qualquer outro objeto cujo tipo seja de uma de suas subclasses diretas ou indiretas.

Princípio da Substituição

public static void soar(Animal animal) {

animal.emitirSom(); //op. polimórfica

}

(8)

• O princípio da substituição também é válido para tipo de retorno.

publicAnimal gereAnimal(bytetipo) { switch(tipo) {

case1:

return newCachorro(); case2:

return new Cavalo(); case3:

return new Porco(); default:

return new Gato();

} }

Pode ser retornado um objeto de qualquer um destes tipos

• Também pode ser utilizado na ligação entre a referência e a instância:

Princípio da Substituição

Animal cachorro, cavalo, gato, porco; cachorro = new Cachorro();

cavalo = new Cavalo();

gato = new Gato();

porco = new Porco();

Note que no exemplo abaixo as referências são do tipo Animal enquanto que os objetos são subtipos da classe Animal.

• Quando o método a ser executado é definido durante a compilação do programa, ocorre o mecanismo de ligação prematura (early binding). • Para a utilização de polimorfismo, a linguagem de programação orientada a objetos deve suportar o conceito de ligação tardia (late binding), onde a definição do método que será efetivamente invocado só ocorre em tempo de execução. O mecanismo de ligação tardia também é conhecido pelos termos dynamic binding ou run-time binding.

Ligação Tardia e Polimorfismo

• A operação emitirSom() é abstrata na classe Animal o que significa que todas as subclasses concretas desta classe abstrata precisam implementá-la. Cada uma delas implementará a operação ao seu modo e teremos, então diversas formas de emissão de som.

public static void soar(Animal animal) {

animal.emitirSom(); //op. polimórfica

}

Ligação Tardia e Polimorfismo

• A definição de qual emitirSom() será utilizado depende de quem a variável animal referencia no momento. Isto só será definido durante a execução do programa e poderá variar. A operação

animal.emitirSom() é uma operação polimórfica.

public static void soar(Animal animal) {

animal.emitirSom(); //op. polimórfica

}

Ligação Tardia e Polimorfismo

• Uma interface define as operações de um tipo sem especificar as suas implementações. Todos os métodos de uma interface são qualificados como public e abstract automaticamente.

public interfaceRepositorioContasIF {

public abstract void inserir(Conta c);

public abstract Conta procurar(String numero) throws

ObjetoNaoEncontradoException;

public abstract boolean existe(String numero);

public abstract void atualizar(Conta c);

}

// A cláusula throws será explicada posteriormente.

Interfaces

(9)

• Todos os métodos de uma interface são qualificados como public e abstract automaticamente e, portanto, o código neste slide é equivalente ao do slide anterior.

public interfaceRepositorioContasIF {

voidinserir(Conta c);

Conta procurar(String numero) throws

ObjetoNaoEncontradoException;

boolean existe(String numero);

voidatualizar(Conta c); }

// A cláusula throws será explicada posteriormente.

Interfaces

• Uma interface só pode conter campos definidos como constantes e que, portanto, precisam ser inicializados. Estes campos são qualificados automaticamente como public, static e final. Os códigos abaixo são

equivalentes.

public interface Voador {

public static final int i= 1;

public abstract void voar();

}

public interface Voador {

int i = 1;

void voar(); }

Interfaces

• Uma classe pode implementar várias interfaces: public classClasseCD implementsInterfaceC, InterfaceD {

public voidmetodoC() {

// Implementar método de InterfaceC...

}

public voidmetodoD() {

// Implementar método de InterfaceD...

} }

• Neste exemplo a classe ClasseCD está obrigada a implementar os métodos das duas interfaces.

Interfaces

• Interfaces não podem conter construtores. • Interfaces podem estender outras interfaces.

public interface InterfaceA {

void metodoA(); }

// Em um outro arquivo

public interface InterfaceB extends InterfaceA {

void metodoB(); }

• A classe que implementar a interface InterfaceB (acima) deverá definir concretamente os métodos abstratos das duas interfaces (InterfaceA e InterfaceB).

Interfaces

• Classes abstratas que implementam interfaces podem postergar a implementação dos métodos abstratos herdados para as suas subclasses concretas.

• Use interfaces sempre que quiser definir operações que algumas classes possam realizar independente de onde elas estejam na árvore de herança.

– Ex.:

• Um morcego é um mamífero que é capaz de voar. • Uma pipa é um brinquedo que é capaz de voar.

• Crie uma interface Voador (por exemplo). Faça com que a classe Morcego estenda Mamífero e implemente Voador. Faça com que a classe Pipa estenda brinquedo e implemente Voador. Aonde for esperado um Voador poderá ser utilizado tanto uma Pipa como um Morcego.

Interfaces

• public: elementos públicos são acessíveis globalmente (de qualquer parte);

• private: classes internas, construtores, atributos e métodos privados são acessíveis somente na própria classe (inclusive nas classes internas a ela);

• protected: elementos protegidos são acessíveis no mesmo pacote e em subclasses (neste caso mesmo não estando no mesmo pacote);

• Sem nenhum modificador: Visível por outros elementos do mesmo pacote. São conhecidos como default ou package-private (termo utilizado pela Sun para designar a visibilidade quando não é utilizado public, protected ou private).

(10)

• O modificador “public” pode ser aplicado a classes, enumerações, interfaces, construtores, métodos e atributos; • A mesma regra acima vale para a visibilidade padrão (default)

“package-private” adotada quando há omissão;

• O modificador “protected” não pode ser aplicado a classes, enumerações e interfaces. Pode ser utilizado em construtores, métodos e atributos;

• A mesma regra acima é válida para o modificador “private”; • Variáveis locais não podem receber atributos de visibilidade.

Elas sempre são visíveis apenas no bloco aonde foram criadas.

Modificadores de Visibilidade

• Quanto a visibilidade, classes externas e

interfaces podem ser ou públicas ou

package-private. Classes e interfaces package-private

só são visíveis dentro do mesmo pacote. Em

alguns editores deve ser marcado a opção

“default” para que a classe seja criada sem

modificador de visibilidade.

• Interfaces devem conter apenas assinaturas

de métodos públicos.

Modificadores de Visibilidade

Modificadores de Visibilidade

• O termo “membro” refere-se a métodos e

atributos de classes e instâncias.

• Um membro não privado é visível por

qualquer classe dentro do mesmo pacote.

• Apenas membros públicos podem ser

visualizados por classes que estejam em

pacotes diferentes e que não sejam

subclasses. No caso de subclasses os membros

protegidos da superclasse também serão

visíveis.

Modificadores de Visibilidade

Visibilidade (S = Sim, N = Não)

Modificador (em Alpha) Package One PackageTwo Alpha Beta AlphaSub Gamma

public S S S S

protected S S S N

sem modificador S S N N

private S N N N

A tabela a seguir mostra quando os membros (atributos e métodos) da classe Alpha são visíveis nas classes do esquema acima, para cada um dos modificadores que podem ser aplicados a eles.

Esquema adaptado de tutorial da Sun:

Referências

Documentos relacionados

•• Não é verdade que as interfaces de usuário devam Não é verdade que as interfaces de usuário devam sempre ser projetadas para maximizar um ou outro sempre ser projetadas

• Substitua as classes de análise por classes de projeto e/ou interfaces dos

Entendendo a centralidade das lutas em favor dos camponeses que se recriam nas contradições da lógica do capital, seja na luta para se reproduzirem enquanto classe

No capítulo quarto da primeira parte da Fenomenologia, Hegel tratará da consciência de si num capítulo intitulado a verdade da certeza de si mesmo. Tal parte

Primeiramente, a instância abstrata de dois elementos, do tipo “ElementExhibitor”, é descrita em notação N3; e logo após a taglib, gerada pelo módulo AIC do sistema, e por fim

Monitoria em disciplinas vinculadas ao Curso de Fisioterapia, exercida por um período de, no mínimo, 1 (um) semestre letivo, com dedicação mínima de 10 (dez) horas semanais.

b. Mantenedores Empresariais: empresas em geral ligadas direta ou indiretamente às etapas de projeto, execução, manutenção e avaliação de instalações e de fornecimento de

Considerações Preliminares: O objeto do presente certame é a formação de “Registro de Preços para futura e eventual aquisição de dietas de sistema fechado(industrializada),