Вы находитесь на странице: 1из 51

Programao Orientada a Objetos Avanada

Neste Captulo:

Os detalhes da herana e a palavra-chave extends Os segredos do polimorfismo Como a palavra-chave instanceof trabalha Como escrever construtores mais elaborados Quando usar classes abstratas (abstract) Como usar interfaces

Reivindicando sua herana


Herana uma caracterstica da POO que permite que voc reuse programas existentes. Em vez de sempre criar uma classe completamente nova para capturar um tipo especfico, voc pode definir uma classe que seja baseada em uma outra existente. Isto permite que variveis e mtodos da classe existente tornem-se automaticamente parte da classe recentemente definida.

Herana significa basicamente que voc pode tornar os mtodos e as variveis no-privadas definidos em uma classe disponveis a uma outra classe.

Voc faz isso definindo um relacionamento entre as classes. A classe que contem j os mtodos e as variveis que voc quer compartilhar chamada superclasse, e a nova classe chamada subclasse. Geralmente, a subclasse prov mtodos adicionais que so especficos s suas necessidades ou que alteram o comportamento de mtodos existentes na superclasse.

No captulo precedente, voc definiu a classe lmpada, que tinha um par de mtodos que poderiam ser usados para lig-la e deslig-la. Todas as lmpadas tm esta habilidade... >> Entretanto, existem diferentes tipos de lmpadas. Voc pde ter uma lmpada de leitura, uma lmpada trmica, ou um par de faris em seu carro. Todas essas so tipos de lmpadas, mas cada uma delas possui suas prprias caractersticas especficas. a lmpada um conceito generalizado - os vrios tipos de lmpadas so especializaes desse conceito.

Expandiremos este conceito de lmpada incluindo outras mquinas eltricas (uma televiso, uma torradeira, um computador, etc) todos so baseados no mesmo conceito de ligar e desligar; - todo tm obviamente funes especficas diferentes.

Definiremos uma nova classe chamada Machine que contm a funcionalidade bsica requerida para todas as mquinas eltricas que voc modelar. Ser uma classe bsica com mtodos para setar e obter um nome para a mquina, lig-la e deslig-la, e um mtodo para consultar o estado da mquina.

publicclassMachine { privateStringname; privatebooleanon; publicvoidsetName(Stringname) { this.name=name; } publicStringgetName() { returnname; } publicvoidturnOn() { if(!on) { on=true; System.out.println(name+ison.); } }

publicvoidturnOff() { if(on) { on=false; System.out.println(name+isoff.); } } publicbooleanisOn() { returnon; } }

Voc poderia instanciar esta classe, mas isso no faria muito sentido... Voc pe o po em uma mquina? >> voc pe esse po em uma torradeira, que um tipo de mquina. Voc no possui nada chamado simplesmente de mquina, embora possua vrios artigos que so mquinas por natureza. A casse Machine s interessa por causa do poder da herana. Iremos reusar Machine, expandindo-a para modelar tipos especficos de mquinas.

Usando a palavra-chave extends


Quando voc especifica que uma classe estende uma outra, voc est criando o relacionamento superclasse-superclasse. A seguir, uma verso da classe Lamp que estende a classe genrica Machine.
publicclassLampextendsMachine { publicLamp() { this(Lamp); } publicLamp(Stringname) { setName(name); } }

Estendendo Machine, voc herda os quatro mtodos definidos nessa classe. como se voc copiasse o contedo de Machine e o colasse diretamente na classe Lamp. Isto reuso de cdigo! Observe os dois construtores providos... O primeiro o construtor default que no recebe nenhum parmetro. Ele chama simplesmente o segundo, que recebe um parmetro String que deve ser um nome que descreva o objeto. >> voc pde passar itens como "Lmpada de Leitura" ou "Luz de Cozinha." Se voc escolher usar o construtor default, o nome "Lamp" ser passado. O segundo construtor invoca o mtodo chamado setName(), que definido em Machine.

Uma classe que cria um objeto Lamp e chama alguns de seus mtodos...
publicclassLampTest { publicstaticvoidmain(String[]args) { Lamplamp=newLamp(); lamp.turnOn(); lamp.turnOff(); } }

Sada, ao se executar esse cdigo...


Lampison. Lampisoff.

O valor Lamp armazenado porque a classe Machine cuidou disso...

O relacionamento que uma subclasse tem com sua superclasse geralmente referido como um relacionamento um . Isto porque sempre vlido dizer que uma lmpada uma mquina. >> contudo, este um relacionamento unidirecional...

As Regras da Herana
1) Herana simples Nas LPOO, h dois tipos de herana: - Com a herana simples, somente uma classe pode ser estendida. - Com a herana mltipla, uma ou mais classes podem ser estendidas.

Java suporta somente herana simples. Isto em grande parte porque a implementao de herana mltipla razoavelmente complexa (e no uma caracterstica que seja to til como se possa pensar...) Pode ser complicado manter um cdigo que deriva sua funcionalidade de mltiplas classes, assim, trabalhar com um modelo de herana simples faz bastante sentido...

Java suporta, sim, herana mltipla quando so usadas interfaces, que so formas especiais de classe (ver adiante...)

2) Voc no pode estender uma classe final. Voc pode usar a palavra-chave final com classes, mtodos, e variveis. Nos trs casos, voc no pode mudar a entidade correspondente. Um exemplo de classe final a classe padro java.lang.String. Se voc tentar estender a classe String, produzir um erro de compilao. OBS: Nem todos os membros so herdados. Quando voc estende uma classe, os nicos mtodos e variveis que voc herda so os mtodos e variveis de instncia no-privados e no-final.

O membros herdados incluem...

quaisquer membros declarados explicitamente como pblicos ou protegidos. membros que no tm nenhum modificador de acesso fornecido. >> quando se usa o modificador protected a um mtodo ou a uma varivel, outros mtodos na classe, em todos os subclasses, e em quaisquer outras classes no mesmo pacote podem acessar essa varivel ou mtodo. >> quando no se fornece um modificador de acesso, o membro considerado "privado ao pacote": todas as classes no mesmo pacote podem acessar esse membro.

Detalhes das regras de acesso para cada um dos quatro nveis do acesso disponveis. Modificador Classe Pacote Subclasse Tudo public protected default private SIM SIM SIM SIM SIM SIM SIM NO SIM SIM NO* NO SIM NO NO NO

* No necessariamente uma subclasse pode acessar mtodos de sua superclasse que sejam privados ao pacote (default)... ... possvel estender uma classe de um pacote, produzindo-se uma subclasse em um diferente pacote.

Variveis com o mesmo nome no so herdadas. >> isto pode conduzir a erros difceis de detectar... A JVM usa sempre a varivel que a "mais local" ao objeto: se uma varivel X for definido na superclasse e na subclasse, uma instncia da subclasse "v" somente sua prpria varivel.

Mtodos funcionam basicamente da mesma maneira... Se voc definir um mtodo com o mesmos nome e parmetros na superclasse e na subclasse, a subclass "v" somente seu prprio mtodo. Entretanto, ter a mesma assinatura do mtodo na superclasse e na subclasse uma prtica comum chamada sobrescrita de mtodo... Voc pode efetivamente forar o acesso ao membro da superclasse usando a palavra-chave super (ver adiante...)

Tipo da Referncia versus Tipo dinmico (run-time)


Observe o cdigo a seguir...
publicclassLampTest2 { publicstaticvoidmain(String[]args) { Machinelamp=newLamp(); lamp.turnOn(); lamp.turnOff(); } }

O tipo da varivel lamp Machine (a classe genrica). O que acontecer quando da execuo deste cdigo?

Exatamente a mesma coisa que no examplo anterior de (LampTest) A primeira linha do mtodo main() cria um novo objeto Lamp (palavrachave new) e atribui sua referncia a uma varivel do tipo Machine. O que se encontra a direita do operador de atribuio chamado tipo dinmico. O que se encontra a direita do operador chamado tipo da referncia.

OBS: O tipo dinmico de um objeto no precisa ser o mesmo da varivel que o referencia. Ele pode ser uma subclasse do tipo da referncia. >> o tipo dinmico o tipo real ...

No exemplo, o tipo da referncia Machine, o que vlido porque Machine uma superclasse do tipo dinmico Lamp (Um objeto Lamp tambm um objeto Machine...)

Por que no fazer simplesmente o tipo da referncia ser sempre o mesmo do tipo dinmico? Para responder, vamos adicionar uma nova classe chamada Toaster.
publicclassToasterextendsMachine { publicToaster() { this(Toaster); } publicToaster(Stringname) { setName(name); } }

Assim como a classe Lamp, a classe Toaster define somente dois construtores, simplesmente herdando toda sua funcionalidade da superclasse. Como Toaster estende tambm Machine, aplica-se o acima referido sobre tipo da referncia e tipo dinmico. O cdigo AllMachines define um array construdo para armazenar todas as mquinas possudas por uma pessoa. Isto incluiria qualquer coisa que possa ser considerada uma mquina.

Um array deve sempre conter elementos do mesmo tipo. Uma lmpada no uma torradeira... Assim, a princpio, pareceria que no h nenhuma maneira de armazenar ambos os tipos de objetos no mesmo array. Entretanto, como Lamp e Toaster derivam da classe Machine, h uma maneira de armazen-los juntos. O array carregar elementos que compartilharo o mesmo tipo de referncia; o tipo dinmico no tem que ser o mesmo.

Para arrays de objetos, o tipo da referncia simplesmente determina o tipo bsico de cada elemento; os valores dos elementos podem ser diferentes.

publicclassAllMachines { publicstaticvoidmain(String[]args) { Machine[]machs=newMachine[3]; MachinemachOne=newLamp(Readinglamp); MachinemachTwo=newToaster(4sliceToaster); MachinemachThree=newLamp(Kitchenlight); machs[0]=machOne; machs[1]=machTwo; machs[2]=machThree; for(inti=0;i<machs.length;i++) { machs[i].turnOn(); machs[i].turnOff(); } } }

Sada: Reading lamp is on. Reading lamp is off. 4-slice Toaster is on. 4-slice Toaster is off. Kitchen light is on. Kitchen light is off. Est acontecendo invocao virtual de mtodos . >> a JVM decide qual verso especfica de um mtodo a chamar em tempo de execuo. >> A JVM sempre invoca o mtodo relativo ao tipo dinmico, independentemente do tipo da referncia.

OBS: somente mtodos de instncia esto envolvidos com invocao virtual de mtodos . Qualquer mtodo esttico sempre vinculado ao tipo da referncia... Invocao virtual de mtodos referida tambm como late binding (amarrao ou vinculao) porque os mtodos de instncia no so vinculados em tempo de compilao.

Variveis so vinculadas ao tipo da Referncia

Embora mtodos possam fazer uso da invocao virtual de mtodos, as variveis no podem.

Variveis so sempre vinculadas ao tipo da referncia. Isto importante compreender se voc fornecer o mesmo nome de varivel na superclasse e em uma subclasse.

Exemplo.
publicclassSuperVariableDemo { publicStringstr=Superclass; } publicclassSubVariableDemoextendsSuperVariableDemo { publicStringstr=Subclass; publicstaticvoidmain(String[]args) { SuperVariableDemosd=newSubVariableDemo(); System.out.println(sd.str); } }

A sada ser sempre Superclass mesmo que o tipo dinmico seja SubVariableDemo. OBS: No tpico definir variveis pblicas (neste caso, emprega-se apenas a ttulo de exemplificao)

Expandindo as Subclasses Anteriormente, herdou-se simplesmente todo o cdigo necessrio nas duass subclasses, Lamp e Toaster. Entretanto, mais comum as subclasses proverem funcionalidades alm dos mtodos bsicos oriundos das superclass. Exemplo,
publicclassToaster2extendsMachine { privateinttemp; privateintmaxTemp=280; privateintminTemp=70; publicToaster2() { this(Toaster); }

publicToaster2(Stringname) { this(name,70,280); } publicToaster2(Stringname,intminTemp,intmaxTemp) { setName(name); this.minTemp=minTemp; this.maxTemp=maxTemp; this.temp=this.minTemp; }

publicvoidheatUp(){ System.out.println(getName()+isheatingup.); while(temp!=maxTemp&&isOn()) { System.out.println(getName()+isnow+ temp+degrees.); temp+=35; } System.out.println(getName()+heatedto+ temp+degrees.); } publicvoidcoolDown(){ System.out.println(getName()+iscoolingdown.); while(temp!=minTemp){ System.out.println(getName()+isnow+ temp+degrees.); temp=35; } System.out.println(getName()+cooledto+ temp+degrees.); } }

publicclassToaster2Test { publicstaticvoidmain(String[]args) { Toaster2t=newToaster2(); t.turnOn();//definedinMachine t.heatUp();//definedinToaster2 t.coolDown();//definedinToaster2 t.turnOff();//definedinMachine } }

Sada correspondente: Toaster Toaster Toaster Toaster Toaster is on. is heating up. is now 70 degrees. is now 105 degrees. is now 140 degrees.

Toaster Toaster Toaster Toaster Toaster Toaster Toaster Toaster Toaster Toaster Toaster Toaster Toaster

is now 175 degrees. is now 210 degrees. is now 245 degrees. heated to 280 degrees. is cooling down. is now 280 degrees. is now 245 degrees. is now 210 degrees. is now 175 degrees. is now 140 degrees. is now 105 degrees. cooled to 70 degrees. is off.

A Hierarquia de classes In this chapter, you have already created some classes, including Machine, Lamp, and Toaster2. These classes form a hierarchy, as shown here: Quando voc est estendendo classes, uma boa idia retratar os relacionamentos resultantes em uma hierarquia. Neste captulo, voc j criou algumas classes, como Machine, Lamp e Toaster2. Estas classes formam uma hierarquia:

Esta uma representao visual do relacionamento superclasse-subclasse. Deste diagrama, voc pode extrair algumas concluses, mesmo sem ver o cdigo fonte.. Uma lmpada sempre uma mquina. Um Toaster2 sempre uma mquina. Uma mquina no uma lmpada nem um Toaster2. Uma lmpada no um Toaster2.

No h nenhum relacionamento entre as classes lmpada e Toaster2 exceto que esto na mesma hierarquia. >> por estar na mesma hierarquia, elas compartilham superclasses comuns, como mostra o diagrama. Quando se tem uma coleo grande de classes definidas, freqentemente til criar um diagrama como este, de modo que se possa prontamente identificar superclasses e subclasses.

At agora, suas subclasses possuem uma nica classe acima delas na hierarquia. Contudo, pode-se estender uma classe, que estende outra e assim sucessivamente.

Quanto mais superclasses se tem, mais memria ser necessria ao se instanciar um objeto. >> Os membros de instncia de cada uma das classes acima na hierarquia devero ser inicializados pela JVM.

A classe Object A hierarquia acima no est realmente completa... Outra classes est envolvida: a classe java.lang.Object . Object a classe bsica em qualquer hierarquia de objetos...

So the following two class declarations are equivalent: public class Machine public class Machine extends Object Because the Object class is always part of your class hierarchy, you can always use Object as a reference type. ...you can create a generic array that holds any type of object with the following code. Todas as classes que voc definir estendem diretamente Object a menos que voc fornea explicitamente uma clusula extends. A nica classe em Java que no estende nenhuma outra classe exatamente essa classe bsica, objeto.

Assim as duas declaraes de classe seguintes so equivalentes: public class Machine public class Machine extends Object Como a classe Object sempre parte de sua hierarquia da classe, voc pode sempre usar Object como um tipo da referncia. ... pode-se criar um array genrico que armazene qualquer tipo de objeto com o seguinte cdigo. Object [] anyObjects = new Object[10];

Os nicos elementos que no podem pertencer a esse array so tipos primitivos...

A Regra de Tipos da Referncia para Mtodos J se viu que: o tipo da referncia de um objeto no tem que ser o mesmo que o tipo dinmico... Um detalhe importante... Se voc tentar chamar um mtodo atravs de uma referncia a um objeto, esse mtodo deve ser definido na classe do tipo da referncia! Voc no pode chamar diretamente um mtodo definido unicamente em uma subclasse referenciando esse objeto com o tipo da superclasse. Na classe Toaster2, quatro mtodos so definidos somente na subclasse.

Assim, se voc tentar fazer o seguinte, que acontecer? Machine mach = new Toaster2(); mach.turnOn(); mach.heatUp();

Este cdigo nem sequer compilaria porque o compilador v que nenhum mtodo heatUp() est definido na classe Machine.

O operador instanceof e converso (casting) de objetos O operador instanceof pode ser usado para verificar um tipo dinmico especfico, independentemente do tipo da referncia empregada. Ex: Criou-se um array que armazena objetos do tipo Machine. Dentro do for, uma verificao feita para se determinar o tipo dinmico de cada um...

publicclassInstanceChecker{ publicstaticvoidmain(String[]args) { Machine[]machs=newMachine[4]; machs[0]=newLamp(); machs[1]=newToaster2(); machs[2]=newToaster2(); machs[3]=newLamp(); for(inti=0;i<machs.length;i++) { System.out.print(Element+i+isa); if(machs[i]instanceofLamp) { System.out.println(Lampobject.); } elseif(machs[i]instanceofToaster2) { System.out.println(Toaster2object.); } } } }

Sada correspondente... Element Element Element Element 0 is a 1 is a 2 is a 3 is a Lamp object. Toaster2 object. Toaster2 object. Lamp object.

Converso (casting) de objetos possvel converter tipos primitivos... (considere float x) int y = (int) x; Descarta-se tudo aps o ponto decimal... obrigatrio o uso do operador de converso para primitivos se a converso para baixo (downcasting).

You do not ever have to explicitly cast if you are widening from a subclass to a superclass. possvel tambm fazer converses com objetos. Se voc tiver uma referncia a uma mquina mas o tipo dinmico realmente Toaster2, voc pode realizar uma converso para ter acesso aos mtodos especficos de Toaster2. Assim como com primitivos, voc deve executar uma converso se voc estiver estreitando da superclasse para uma subclasse. No ser obrigatrio converter explicitamente se voc estiver alargando de uma subclasse a uma superclasse.

Ex: Machine m = new Toaster2(); // upcasting, works fine Toaster2 t = new Machine(); // downcasting, fails Voc pode sempre atribuir um objeto de uma subclass a uma referncia da superclasse, mas voc no pode fazer o oposto a menos que voc faa a converso explcito.

A sintaxe para converso de objetos a mesma que a usada para primitivos...

Ex: Machine m = new Toaster2(); // upcasting, works fine Toaster2 t = (Toaster2)m; // casting makes this work now necessrio cuidado com converso de objetos. Nem sempre o compilador detecta todos os possveis erros, ento seu cdigo pode compilar sem problema, mas pode gerar uma exceo em tempo de execuo. Ex: Se voc tentar converter uma referncia a Machine para uma referncia a Toaster2 ... ?

Вам также может понравиться