Sunteți pe pagina 1din 34

Classes e Instncias 1

3
3
-
-
C
C
l
l
a
a
s
s
s
s
e
e
s
s
e
e
I
I
n
n
s
s
t
t

n
n
c
c
i
i
a
a
s
s

3.1 Definio de classe
Uma classe um objecto especial que serve de molde ou padro para a criao de objectos designados por
instncias da classe, objectos similares, j que possuem a mesma estrutura interna, ou seja, as mesmas
variveis de instncia, o mesmo comportamento, isto , os mesmos mtodos de instncia, e a mesma
interface ou API, pois so capazes de responder s mesmas mensagens.
Neste sentido, como vimos j, uma classe um mdulo onde se especifica quer a estrutura quer o
comportamento das instncias que a partir da mesma pretendemos criar ao longo da execuo de um dado
programa.
Sendo as instncias de uma classe um conjunto de objectos que depois de serem criados, e porque possuem a
mesma interface, respondem ao mesmo conjunto de mensagens, isto , so exteriormente utilizveis de igual
forma, ento, a classe pode tambm ser vista como um tipo.
As classes das linguagens de PPO podem ser ainda vistas como mecanismos de implemementao de Tipos
Abstractos de Dados (TAD), dado que estes, como o seu nome indica, so especificaes abstractas de
propriedades e no implementaes, que as classes podem corporizar.
Finalmente, tal como a Figura 3.1 procura ilustrar, as classes representam ainda um muito importante
mecanismo de partilha de cdigo, dado que os mtodos, que implementam a funcionalidade de todas as
suas instncias, tm o seu cdigo guardado num nico local a sua respectiva classe , contendo as
instncias apenas os valores que representam o seu estado interno.
CLASSE Ponto
Variveis de Instncia
int x;
int y;
Mtodos de Instncia
int cx()
int cy()
void incX(int dx)
boolean impar()
ponto1
ponto2
-7
10
6
-5
...................................

Fi gura 3. 1 Uma Classe e duas das suas instncias
De facto, no fazendo qualquer sentido que, por exemplo, todo o cdigo dos mtodos de instncia de Ponto
tivesse que ser replicado em todas as instncias criadas, o que seria naturalmente uma redundncia e um
desperdcio, j que o cdigo exactamente igual, ento tal cdigo tem uma nica cpia da qual a classe a
natural depositria.
Quando uma instncia de uma determinada classe recebe uma dada mensagem, apenas ter que solicitar
sua classe a execuo do mtodo correspondente, caso tal mtodo exista, execuo que ser realizada sobre o
J JA AV VA A5 5 E E P PR RO OG GR RA AM MA A O O P PO OR R O OB BJ JE EC CT TO OS S ( (F F. . M M R RI IO O M MA AR RT TI IN NS S 2 20 00 06 6) )
2 Classes e Instncias
espao de variveis da instncia receptora, isto , usando os valores das variveis de instncia que constituem
o estado interno actual desta.
No exemplo apresentado na Figura 3.2, o envio da mensagem cx() s duas instncias da classe Ponto
apresentadas geraria resultados diferentes, qualquer que seja o cdigo do mtodo cx(), dado que ponto1 e
ponto2 identificam dois pontos que, tal como podemos verificar pelo exemplo, possuem diferentes valores
para as coordenadas em x em y.
Dado que, ao escrever o cdigo do mtodo cx(), o programador sabe que qualquer instncia de Ponto possui
variveis de instncia designadas por x e y, tal como especificado na classe, ento, tal cdigo passa a ser de
imediato genrico para todas as instncias, ficando o resultado do mesmo apenas dependente dos valores que
tais variveis tiverem no momento em que esta recebe a mensagem.
Saliente-se tambm, mais uma vez, a diferenciao clara entre o que uma mensagem enviada a uma
instncia, e o resultado de tal mensagem ser enviada, que a activao do mtodo que lhe corresponde.
Mensagens e mtodos so, portanto, entidades distintas.
ponto2
-7
6
cx()
-7
ponto1
10
-5
cx()
10

Figura 3.2 Mensagem-receptor-resposta
3.2 Criao de classes: introduo
A noo de classe, tal como foi definida anteriormente, suficientemente clara para que, de imediato,
possam ser criadas algumas classes simples, e estas sejam utilizadas para criar instncias com as quais se
realizem algumas computaes. Vamos igualmente aproveitar a necessidade de definir classes novas para
introduzir gradualmente outros conceitos muito importantes em PPO, analisando como os mesmos esto
representados na linguagem JAVA.
3.2.1 Classe Ponto: requisitos iniciais
Pretende-se com este primeiro pequeno projecto criar uma classe que especifica a estrutura e o
comportamento de objectos do tipo Ponto, que sero instncias de tal classe, e que se pretende que
satisfaam o seguinte conjunto de requisitos:
Os pontos devero possuir coordenadas inteiras;
Dever ser possvel criar pontos com coordenadas iniciais iguais a 0;
Dever ser possvel criar pontos com coordenada em X e coordenada em Y, iguais aos valores dados
como parmetros;
Dever ser possvel saber qual a coordenada em X actual de um ponto;
Dever ser possvel saber qual a coordenada em Y actual de um ponto;
Dever ser possvel incrementar as coordenadas em X e em Y com os valores dados como
parmetro;
Dever ser possvel decrementar as coordenadas em X e em Y com os valores dados como
parmetro;
Dever ser possvel determinar se o ponto tem ambas as coordenadas positivas;
C CC C C CC CL LL LL LL LA AA AA AA AS SS SS SS SS SS SS SS SE EE EE EE ES SS SS SS S E EE EE EE E I II I I II IN NN NN NN NS SS SS SS ST TT TT TT T N NN NN NN NC CC CC CC CI II II II IA AA AA AA AS SS SS SS S
Classes e Instncias 3
Dever ser possvel determinar se o ponto simtrico, ou seja, se dista igualmente do eixo dos X e
do eixo dos Y.
3.2.2 Definio da estrutura
Em PPO, tal como veremos mais adiante, quando se pretende construir uma nova classe, devemos comear
por analisar se tal classe no poder ser definida custa de outras classes j existentes, ou seja, reutilizando o
que j existe em JAVA. No entanto, e porque tal anlise implica possuir j bastantes conhecimentos sobre a
linguagem de programao, em especial sobre as classes j existentes, vamos de momento admitir que esta
nova classe vai ser por ns contruda a partir do zero.
Assim, a primeira deciso ser a que diz respeito definio da estrutura interna de cada um dos pontos
que pretendemos, ou seja, pensarmos quais devero ser as respectivas variveis de instncia (os seus nomes
e os seus tipos).
Neste caso, cada ponto dever ter apenas que conter dois valores de tipo inteiro, um correspondente ao valor
da sua coordenada em X e o outro ao valor da coordenada em Y. Assim sendo, os pontos que pretendemos
criar necessitam de ter duas variveis de instncia a que vamos dar os nomes de x e y e que vo ser do tipo
int.
Vamos, ento, ver como gradualmente vai evoluindo a classe Ponto que se quer construir. A definio de
uma classe , em JAVA, realizada dentro de um bloco que antecedido pela palavra reservada class, qual
se segue o identificador da classe que deve sempre comear por uma letra maiscula. Dentro do bloco, sero
dadas de forma apropriada todas as definies necessrias criao da classe, ou seja, as definies dos
diversos possveis membros da classe (class members). Tais definies consistem, por agora, na declarao
das diversas variveis de instncia e na codificao de cada um dos mtodos de instncia.
Assim, partindo de um esqueleto bsico contendo apenas a identificao da classe, como:
class Ponto {
// definies
}
vamos introduzir a definio de cada varivel de instncia, separando sempre as vrias declaraes com
comentrios que auxiliam legibilidade dos programas.
class Ponto {
// variveis de instncia
int x;
int y;
}
, em geral, boa prtica colocar cada varivel de instncia numa linha separada, e em comentrio indicar o
que representa. no entanto redundante documentar o bvio, como seria o caso neste primeiro exemplo.
3.2.3 Definio do comportamento:
os construtores
Em geral, o primeiro cdigo que se define quando se constri uma classe, o de uns mtodos particulares em
JAVA e C++ designados por construtores, que no so mtodos de instncia, e que so por isso mtodos
especiais dado que apenas so utilizados numa construo JAVA muito particular que tem por objectivo
criar instncias de uma dada classe.
Em JAVA, desde que uma classe tenha j sido definida, por exemplo uma classe designada por Ponto, de
imediato possvel criar instncias dessa classe se usarmos uma das seguintes construes sintcticas:
Ponto p1 = new Ponto();
ou de forma equivalente,
J JA AV VA A5 5 E E P PR RO OG GR RA AM MA A O O P PO OR R O OB BJ JE EC CT TO OS S ( (F F. . M M R RI IO O M MA AR RT TI IN NS S 2 20 00 06 6) )
4 Classes e Instncias
Ponto p1;
p1 = new Ponto();
Em ambos os casos comeamos por declarar uma varivel p1 como sendo do tipo Ponto, ou seja, capaz de
referenciar objectos que so instncias de tal classe. Em seguida, ainda que de formas diferentes, a essa
varivel associado o resultado da execuo da expresso new Ponto(). Esta expresso, que traduzida se
torna clara, corresponde criao de uma nova instncia da classe Ponto pela execuo do mtodo
Ponto(), mtodo especial com nome igual ao da classe.
A nova instncia referenciada atravs da varivel p1. O mtodo especial Ponto() que em conjunto com
new capaz de construir instncias da classe Ponto designa-se, por tal razo, um construtor.
Em JAVA, para cada classe de nome, por exemplo, C, automaticamente associado um construtor C(),
capaz de criar instncias de tal classe quando usado em conjunto com a palavra reservada new em expresses
como new C().
Adicionalmente, JAVA permite ao programador criar tantos construtores quantos os que achar necessrios
para criar instncias de dada classe, impondo apenas uma regra bvia: todos os construtores possuem o
mesmo nome da classe, podendo diferir, no entanto, quanto ao nmero e tipo dos seus parmetros.
No nosso exemplo, caso nenhum outro construtor fosse por ns definido na classe Ponto, a expresso
usando o operador new, como em:
Ponto p1 = new Ponto();
associaria varivel p1 uma instncia de Ponto que teria nas suas variveis de instncia x e y o valor inicial
0, dado estas serem do tipo int e 0 ser o valor predefinido para variveis deste tipo. Como facilmente se
compreende, estes so valores iniciais adequados para um objecto do tipo Ponto. Porm, vamos desde j
habituar-nos a redefinir o construtor por omisso, realizando a sua definio de forma explcita para que no
haja qualquer ambiguidade.
Portanto, e em funo da anlise realizada, vamos dar uma definio nossa para o construtor Ponto(), que
ser executado em vez do referido construtor por omisso, ou seja, que se vai sobrepor ao construtor por
omisso, e que vai atribuir explicitamente o valor 0 a cada varivel de instncia do ponto criado. O cdigo
do mesmo seria, nesta fase, simplesmente:
Ponto() { x = 0; y = 0; }
Os construtores de uma classe so todos mtodos especiais que so declarados na classe, tendo por
identificador o exacto nome da classe, e tendo por argumentos valores de qualquer tipo de dados, e cujo
objectivo criar instncias de tal classe que sejam de imediato manipulveis. Os construtores servem apenas
para criar novas instncias de uma dada classe, pelo que no faz sentido que tenham que especificar um
qualquer tipo de resultado.
Por outro lado, sempre possvel, e muitas vezes bastante til, definir mais de um construtor de instncias de
uma dada classe, construtores que, em geral, apenas diferem nos valores iniciais atribudos s variveis de
instncia, ou quanto forma de atribuio de tais valores a tais variveis (como veremos mais tarde).
Se pretendermos no exemplo em questo criar instncias da classe Ponto atribuindo de imediato s suas
variveis de instncia valores iniciais dados como parmetro, ento, poderemos criar um construtor adicional
que receba as coordenadas como parmetro e as atribua s variveis de instncia da instncia criada, como:
Ponto(int cx, int cy) { x = cx; y = cy; }
A nossa classe Ponto tem neste momento apenas construtores e estrutura, ou seja, no tem definido qualquer
comportamento dado pelo conjunto de operaes ou mtodos, quer de consulta quer de modificao , pelo
C CC C C CC CL LL LL LL LA AA AA AA AS SS SS SS SS SS SS SS SE EE EE EE ES SS SS SS S E EE EE EE E I II I I II IN NN NN NN NS SS SS SS ST TT TT TT T N NN NN NN NC CC CC CC CI II II II IA AA AA AA AS SS SS SS S
Classes e Instncias 5
que, se crissemos neste momento instncias da classe, nada poderamos realizar com as mesmas. Os
mtodos de instncia so, portanto, mtodos essenciais para que possamos utilizar as instncias.
class Ponto {
// Construtores
Ponto() {
x = 0; y = 0;
}
Ponto(int cx, int cy) {
x = cx; y = cy;
}
// Variveis de Instncia
int x;
int y;
...
}
3.2.4 Definio do comportamento:
os mtodos de instncia
Vamos agora iniciar o processo de programar em JAVA os mtodos de instncia que iro ser os
responsveis pelo comportamento das instncias de Ponto quando recebem as mensagens a que devero ser
capazes de responder.
Dado que a estrutura sintctica geral para a completa definio em JAVA de um mtodo de instncia
relativamente complexa, vamos enveredar por um processo de apresentao da mesma em funo das
necessidades, isto , as mais complexas particularidades definicionais sero apresentadas sempre que,
perante um exemplo, as mesmas tenham que ser introduzidas.
Vamos tambm, desde j, introduzir uma regra crucial para uma correcta programao em PPO, regra
apresentada no captulo 1, e que prope o seguinte:
Qualquer que seja a linguagem de PPO usada, a nica forma de se poder garantir, mesmo usando os
mecanismos tpicos da PPO, que estamos a programar entidades independentes do contexto e, assim,
reutilizveis, garantir que nenhuma cpsula faz acesso directo s variveis de instncia de outra
cpsula, mas que apenas invoca por mensagens os mtodos de acesso a tais valores, mtodos que
para tal devem ser programados nas cpsulas.
Esta regra, extraordinariamente importante, impe duplas responsabilidades aos que tm que implementar as
classes que vo gerar instncias. Por um lado, devem saber que, na definio dos mtodos de instncia de um
dado objecto, no devem escrever cdigo que corresponda a aceder directamente s variveis de instncia de
um qualquer outro objecto, pois tal gera cdigo dependente da implementao interna de tal objecto, logo
dependente do contexto. Por outro lado, para que do exterior se possa ter acesso aos valores das variveis de
instncia de uma forma correcta, ento, necessrio que as interfaces forneam os mtodos adequados a tal
acesso (mtodos de consulta das variveis).
Note-se ainda que estas regras correspondem a princpios de programao que no so verificados pelos
compiladores, pelo que compete aos programadores apenas o seu cumprimento. De facto, mesmo as mais
evoludas linguagens de PPO possibilitam, ou seja, no detectam nem em tempo de compilao nem noutro
qualquer, situaes de completa infraco desta regra to importante.
Por exemplo, em JAVA, e usando o que apenas foi at agora definido para a classe Ponto, uma classe
cliente da classe Ponto, ou seja, uma classe que esteja a usar esta classe, poderia ter um mtodo que,
necessitando de ter o valor actual da varivel de instncia x da instncia referenciada pela varivel p1,
contivesse o cdigo seguinte:
int cx = p1.x;
J JA AV VA A5 5 E E P PR RO OG GR RA AM MA A O O P PO OR R O OB BJ JE EC CT TO OS S ( (F F. . M M R RI IO O M MA AR RT TI IN NS S 2 20 00 06 6) )
6 Classes e Instncias
Este cdigo passaria como correcto no compilador de JAVA. De facto, o operador ponto (.) funciona em
JAVA, tal como em vrias outras linguagens, como um selector, que possibilita aceder por nome a uma
varivel, ou mtodo, do objecto referenciado pela varivel escrita do seu lado esquerdo. Poderamos at,
usando tal construo, alterar directamente o valor da varivel de instncia y de p1 escrevendo, por
exemplo:
p1.y = -9;
Porm, do ponto de vista dos princpios fundamentais da PPO, este cdigo est formalmente incorrecto e
nem sequer deveria ser aceite como correcto na fase de compilao, dado conter uma expresso baseada no
acesso directo representao interna de outro objecto. Tal como anteriormente foi demonstrado, o que
acontece ao cdigo fonte desta classe, que cliente da classe Ponto, caso a classe Ponto seja redefinida,
por exemplo, alterando o nome da varivel de instncia ou, pior ainda, a representao do valor inteiro, que
se torna inutilizvel dado usar uma representao que passa a estar errada. Por outro lado, e do ponto de vista
da instncia p1, qualquer classe cliente poder deste modo modificar o seu estado interno a qualquer
momento e sem qualquer controlo desta.
, no entanto, comum ler-se em livros sobre programao por objectos usando a linguagem JAVA ou outras,
publicados por algumas editoras internacionais de nome credvel nesta rea, a informao de que, caso se
pretenda ter acesso a uma varivel x de uma instncia referenciada, por exemplo, como c, se deve escrever
c.x, frase que est sintacticamente correcta.
Obviamente que, dentro dos princpios de programao que vimos defendendo para que, de facto, possamos
atingir certos objectivos no desenvolvimento de aplicaes de alguma escala, em particular com o auxlio de
certas construes oferecidas pelo paradigma da PPO, tal tipo de codificao , como se provou,
completamente desaconselhvel.
Naturalmente que, quando no so estes os objectivos a perseguir na utilizao de JAVA e das suas
construes de PPO, mas antes, por exemplo, mxima eficincia do cdigo, custe o que tal possa custar em
correco de erros, reutilizao e generalidade, ento, tais construes podem ser usadas, sendo certo que
sacrificam tais objectivos, que, no nosso caso, se consideram fundamentais.
Exactamente por estas razes, no livro The Java Language Specification, dos autores da linguagem JAVA, a
primeira regra por estes apresentada, relativamente aos nomes a atribuir aos mtodos, sugere que todos os
mtodos que fazem acesso ao valor de uma varivel de instncia de nome genrico x devem ser designados
por getX (ex.: getNome(), getConta(), etc.). Por outro lado, todos os mtodos que alteram o valor de
uma varivel de instncia x devem ser designados por setX (ex.: setNome(), setConta(), etc.), ou seja,
desta forma desaconselhando indirectamente a manipulao do identificador e do valor da varivel usando
um selector.
Os mtodos do tipo getX(), porque realizam a consulta do valor de dada varivel e devolvem esse valor
como resultado, designam-se por interrogadores ou selectores. Tipicamente devolvem um resultado que
do mesmo tipo da varivel consultada e no possuem parmetros de entrada. Os mtodos do tipo setX(),
dado terem por objectivo alterar o valor da varivel de instncia, designam-se por modificadores e, em
geral, tm parmetros de entrada mas no devolvem qualquer resultado. Naturalmente que no obrigatrio
usar exactamente set e get, podendo usar-se identificadores que reflictam no entanto a semntica (ex.:
mudaX(), alteraX(), etc.).
A sintaxe geral para a definio de um mtodo de instncia consiste em JAVA na definio do seu
cabealho (header) e do seu corpo (body). A estrutura mais bsica de declarao do cabealho de um
mtodo a seguinte:
<tipo de resultado> <identificador> ( tipo nome_parmetro, )
O <identificador> de um mtodo uma sequncia de letras e dgitos, devendo o primeiro carcter ser uma
letra e, por razes de estilo, minscula.
C CC C C CC CL LL LL LL LA AA AA AA AS SS SS SS SS SS SS SS SE EE EE EE ES SS SS SS S E EE EE EE E I II I I II IN NN NN NN NS SS SS SS ST TT TT TT T N NN NN NN NC CC CC CC CI II II II IA AA AA AA AS SS SS SS S
Classes e Instncias 7
A lista de parmetros formais <pares tipo-nome: parmetros> constituda por zero ou mais pares tipo
nome_parmetro, que definem os tipos e identificadores dos parmetros formais do mtodo. Os tipos, de
momento, tanto podem ser identificadores de tipos simples, como arrays ou nomes de classes. Esta lista, que
pode ser vazia, delimitada por parntesis.
O <tipo de resultado> de um mtodo, de momento, poder ser um identificador de um dos tipos simples da
linguagem (ex.: int, boolean, real, float, char, etc.), um array de um dado tipo, simples ou
referenciado, ex.: int[] ou String[], o nome de uma qualquer classe (ex.: String, Date, Point, etc.) e,
ainda, a palavra reservada void caso o mtodo no devolva qualquer resultado.
Apresentam-se, em seguida, alguns exemplos deste tipo de cabealhos, usualmente designados tambm
como assinaturas dos mtodos (se excluirmos o tipo do resultado):
int getConta()
boolean maiorQue(int valor)
void setValor(int valor)
boolean valorEntre(real min, real max)
String toString()
nt[] notasAcimaDe(int NotaRef)
Triangulo maiorTtri(Triangulo t2)
A assinatura (signature) de um mtodo constituda pelo nome do mtodo e pelos seus parmetros (em
nmero, tipo e ordem). A assinatura de um mtodo um elemento caracterizador do mesmo e, como
veremos mais tarde, um elemento importante na resoluo de conflitos que podem surgir na definio de
classes, dado que a assinatura de um mtodo, tal como o nome indica, uma chave que deve ser nica para
que o interpretador de JAVA possa aceder ao cdigo do mesmo para o executar. Assim, no devem existir
conflitos de assinaturas em mtodos da mesma classe.
O corpo de um mtodo definido como sendo um bloco de instrues, tendo por delimitadores as usuais
chavetas { }. Caso o mtodo devolva um resultado, este ser o valor resultante do clculo do valor da
expresso que est associada primeira instruo return que for executada, instruo essa que, em boa
programao, aparecer uma s vez no cdigo do mtodo, em geral no final do mesmo (salvo raras
excepes).
Retomando o exemplo da classe Ponto, podemos agora escrever o mtodo de instncia que deve devolver
como resultado o valor actual da varivel de instncia x, mtodo que deve poder ser invocado do exterior da
classe, logo, sendo pblico:
O cdigo de tal mtodo, usando a regra atrs referida para os nomes, ser o seguinte:
// interrogador selector
int getx() { return x; }
Como se pode verificar, o mtodo limita-se a devolver o valor da varivel de instncia x. Assim, e mais uma
vez admitindo que a varivel p1 referencia uma instncia de Ponto, qualquer objecto externo por
exemplo, criado no contexto de um programa principal contendo o mtodo main() onde se criariam
diversos pontos para com eles testarmos vrias das operaes que estamos a programar , passa a poder ter
acesso ao valor da varivel de instncia de p1, escrevendo o cdigo que corresponde ao envio da mensagem
que activa o mtodo getx(), como por exemplo:
int cx = p1.getx();
System.out.println(" X de p1 = " + cx);
ou de forma equivalente e mais simples:
System.out.println(" X de p1 = " + p1.getx());
cdigo que permitiria consultar o valor actual da coordenada em x de p1, e, atravs da instruo bsica de
JAVA para output em ecr, apresentar tal valor ao utilizador. O mesmo faramos para a coordenada em y.
Vamos, em seguida, desenvolver outros mtodos que, conforme os requisitos originais, se pretendem ver
J JA AV VA A5 5 E E P PR RO OG GR RA AM MA A O O P PO OR R O OB BJ JE EC CT TO OS S ( (F F. . M M R RI IO O M MA AR RT TI IN NS S 2 20 00 06 6) )
8 Classes e Instncias
implementados na classe Ponto. Assim, pretende-se programar um mtodo modificador que incremente x e
y com os valores dados como parmetro. Tal mtodo ter como resultado void, e ser designado por
incCoord, tendo os dois parmetros de entrada que vo incrementar os valores de x e de y:
// modificador incremento das Coordenadas
void incCoord(int deltaX, int deltaY) {
x = x + deltaX; y = y + deltaY ;
}
No devolvendo este mtodo qualquer resultado, a sua invocao no cdigo de um objecto exterior ou de um
programa principal teria a seguinte forma:
p1.incCoord(dx, dy);
ou seja, o objecto exterior ao invocar tal mtodo altera o estado interno de p1, mas, embora o ponto receptor
reaja a tal invocao mudando o seu estado interno, o objecto exterior (invocador) no necessita de receber
qualquer resultado (nem poderia porque o mtodo tem void por resultado). Note-se mais uma vez, pelo
exemplo, a similaridade entre a forma sintctica da mensagem e a assinatura do mtodo, ou seja, o envio da
mensagem resulta na invocao do mtodo sintacticamente correspondente.
Vamos em seguida desenvolver o cdigo do mtodo modificador que permite que as coordenadas sejam
decrementadas. O cdigo do mtodo ser, neste caso o seguinte:
// modificador decremento das Coordenadas
void decCoord(int deltaX, int deltaY) {
x -= deltaX; y -= deltaY;
}
3.2.5 A referncia this
No desenvolvimento do cdigo dos mtodos de instncia de uma dada classe, h por vezes a necessidade de
referenciarmos ou uma varivel de instncia prpria, interna ao prprio objecto que estamos a programar, ou,
at, invocar um mtodo interno de tal objecto. Porm, se ainda estamos a programar tal objecto, ele ainda
no tem identificador para ser referenciado por nome. Assim, como referenci-lo?
Em JAVA, sempre que dentro do cdigo de um dado objecto pretendermos ter acesso a uma varivel ou
mtodo do mesmo objecto, podemos faz-lo usando a palavra reservada this, que uma referncia
especial.
Um exemplo muito comum da necessidade de utilizao de this, e que at agora propositadamente
evitamos, ocorre quando os identificadores dos parmetros de entrada coincidem com os nomes das variveis
de instncia (o que normal por serem mnemnicos e portanto mais fceis de perceber, quer na API quer no
cdigo do objecto).
Por exemplo, se num construtor tal acontecesse, teramos ento,
Ponto(int x, int y) {
this.x = x; this.y = y;
}
em que this.x distingue claramente que se trata da varivel de instncia x, de modo a resolver a potencial
ambiguidade. Assim se far sempre que tal seja necessrio, por razes de clareza do cdigo.
Quanto aos mtodos, a questo que se coloca no ser tanto a da ambiguidade, mas antes a necessidade de,
na codificao de um mtodo, se pretender invocar um outro mtodo j definido. Vejamos um exemplo
simples utilizando o mtodo decCoord(int, int) atrs codificado. Imaginemos que nos era pedido para
programarmos um mtodo que apenas decrementasse a coordenada em X.
A primeira soluo bvia seria a seguinte:
C CC C C CC CL LL LL LL LA AA AA AA AS SS SS SS SS SS SS SS SE EE EE EE ES SS SS SS S E EE EE EE E I II I I II IN NN NN NN NS SS SS SS ST TT TT TT T N NN NN NN NC CC CC CC CI II II II IA AA AA AA AS SS SS SS S
Classes e Instncias 9
// modificador decrementa Coordenada X
void decCoordX(int deltaX) {
x -= deltaX;
}
Outra possvel soluo seria, reutilizando o mtodo j antes definido:
// modificador decrementa Coordenada X
void decCoordX(int deltaX) {
this.decCoord(deltaX, 0); // invoca decCoord() local
}
usando this.decCoord(), em que this uma referncia especial para o prprio objecto (contexto) que
estamos a definir, lendo-se: invocar o mtodo local decCoord() ou, at, invocar o mtodo decCoord()
deste objecto. O mtodo invocado com o segundo parmetro igual a 0 para que a coordenada em Y no
seja alterada.
boa prtica escrever this.m() quando estamos a invocar um mtodo interno. No entanto, se tivssemos
apenas escrito decCoord(deltaX, 0), o compilador adicionaria a referncia this de forma automtica.
Nas variveis de instncia, this apenas deve ser usada quando houver colises com identificadores de
parmetros, j que as variveis de instncia so, por definio, locais ao objecto.

Vamos, agora, continuar com o desenvolvimento do cdigo dos mtodos de instncia restantes. O cdigo do
mtodo que determina se um ponto tem ambas as coordenadas positivas dever devolver como resultado um
boolean, no tendo parmetros de entrada:
/* determina se um ponto tem ambas as
coordenadas positivas */
boolean coordPos() {
return x > 0 && y > 0 ;
}
Aproveitamos para introduzir os comentrios multilinha de JAVA que so todas as frases escritas
delimitadas por /* */ e que o compilador despreza.
Aps estes pequenos primeiros exemplos de definio de mtodos de instncia, j possvel chamar a
ateno para o facto de que, quando temos que definir o cdigo de tais mtodos, e no sentido de tornar tal
processo mais fcil, nos deveremos sempre colocar, de um ponto de vista conceptual, numa posio
semelhante da prpria instncia que recebe a correspondente mensagem. Isto , ser sempre mais simples
codificar tais mtodos se pudermos atribuir algum grau de antropomorfismo aos objectos que estamos a
programar, ou assumindo ns prprios a sua posio de "prestao de um servio", em qualquer dos casos
procurando sempre a melhor resposta seguinte questo que fundamental: com a minha estrutura interna
e com o auxlio de tudo o que o ambiente me permite utilizar, como devo programar uma resposta correcta
ou apenas modificar o meu estado interno, em funo dos requisitos apresentados, mensagem m que me foi
enviada?.
Esta noo de ter que programar a prestao de um servio (seja ele um resultado de facto ou apenas uma
alterao interna) em resposta recepo de um pedido formal solicitado sob a forma de uma mensagem,
crucial para a compreenso e para a boa utilizao do paradigma da PPO, dado ser esta a sua essncia.

Por outro lado, e at por tudo o que j vimos anteriormente, sendo o modelo computacional bsico da PPO o
envio de uma mensagem a um objecto receptor, a frase fundamental da escrita de cdigo em PPO, e
naturalmente em JAVA, ser, sendo obj um objecto e m() uma mensagem, a seguinte frase de estrutura
bsica:
obj.m();
que, a partir desta forma mais simples em que a mensagem no tem argumentos e no h resultado do
mtodo invocado, se generaliza para todas as outras formas, que so:
obj.m(p1, p2, , pn); // modificador com parmetros
res = obj.m(); // interrogador simples
res = obj.m(p1, p2, , pn); // interrogador com parmetros
J JA AV VA A5 5 E E P PR RO OG GR RA AM MA A O O P PO OR R O OB BJ JE EC CT TO OS S ( (F F. . M M R RI IO O M MA AR RT TI IN NS S 2 20 00 06 6) )
10 Classes e Instncias
As mensagens podem por vezes ser escritas como uma sequncia, obj.m1().m2(), devendo ser interpretadas
da esquerda para a direita, isto , a mensagem m2() ser enviada ao objecto que o resultado obtido aps o
envio de m1() a obj.
Note-se que, dentro desta metodologia que aqui se est a procurar definir, nunca iremos criar mtodos que,
em simultneo, modifiquem o estado interno de um objecto e devolvam um resultado para o exterior. Isto ,
cada mtodo ou um modificador ou um interrogador, e bastar verificar o pattern da sua utilizao (ver
as frases acima) para se saber perfeitamente o que significa tal linha de cdigo.
O mtodo seguinte visa determinar se um ponto dista igualmente do eixo dos X e do eixo dos Y, isto , se,
em valor absoluto, as suas coordenadas x e y so iguais. Ora, a funo que calcula o valor absoluto de um
inteiro (ou de outro tipo numrico qualquer) encontra-se em JAVA codificada numa classe chamada Math.
Vamos em seguida ver como que em JAVA podemos ter acesso a classes que esto predefinidas e saber
como podemos realizar a sua importao para o contexto das classes que estamos a definir, por forma a
podermos utilizar tudo o que nesta tenha sido definido.
3.2.6 Packages e importao de classes
Em JAVA, um ficheiro que contenha cdigo fonte tem a extenso .java e um nome igual ao da classe pblica
definida em tal ficheiro. O ficheiro onde colocaramos a nossa classe Ponto teria pois a designao
Ponto.java e conteria apenas a definio da classe Ponto. Aps a compilao de uma classe, gerado um
ficheiro de byte-codes, designado por ficheiro de classe, que ter o mesmo nome da classe compilada mas
extenso .class. A compilao do ficheiro Ponto.java daria, pois, origem ao ficheiro Ponto.class, ficheiro
este que, s por si, no executvel pelo interpretador de JAVA pois no possui um mtodo main() para
incio de execuo. Por isso, em geral, constri-se uma pequena classe contendo tal mtodo main() no qual
se usa a classe definida, Ponto, para criar instncias e com estas testar os mtodos desenvolvidos, tal como
se tal constitusse um programa principal de teste da classe (ver exemplo adiante).
Por outro lado, em JAVA, as classes so em geral agrupadas em packages, desta forma sendo possvel
manter as classes em compartimentos ou pacotes distintos, em geral agrupadas em funo da sua
funcionalidade. Em especial, tal facto facilita a procura das classes, dado que os packages tm nomes
bastante representativos da funcionalidade das classes que os constituem.
Por exemplo, o package de JAVA que contm todas as classes relacionadas com as operaes de
input/output designa-se por package java.io. O package de JAVA que contm um conjunto de classes que
implementam estruturas e tipos de dados de grande utilidade geral designa-se por package java.util; o
package java.lang rene todas as classes fundamentais execuo de programas JAVA. Em JAVA, existem
actualmente definidos cerca de 130 diferentes packages. Ao longo deste livro necessitaremos de, no mximo,
utilizar classes de seis destes packages.
Qualquer classe ou membro de uma classe pode ser referenciado de forma absoluta usando como prefixo o
nome do package, seguido do identificador da entidade a que se pretende aceder como, por exemplo, em:
comp = java.Math.min(lista.size(), MIN);
java.lang.System.out.println("abc");
java.util.Scanner;
Porm, sempre que na definio de uma classe necessitarmos de usar classes pertencentes a um dado
package, poderemos sempre usar uma clusula de importao, que torna os elementos importados
disponveis na definio da classe que os importa, podendo, a partir da, as classes serem designadas pelos
seus nomes abreviados.
As clusulas de importao, obrigatoriamente escritas antes do incio da definio da classe, permitem
realizar importaes qualificadas (especficas), em qualquer nmero, tal como por exemplo em:
import java.lang.String;
import java.zip.ZipInputStream;
import java.io.BufferedReader;
C CC C C CC CL LL LL LL LA AA AA AA AS SS SS SS SS SS SS SS SE EE EE EE ES SS SS SS S E EE EE EE E I II I I II IN NN NN NN NS SS SS SS ST TT TT TT T N NN NN NN NC CC CC CC CI II II II IA AA AA AA AS SS SS SS S
Classes e Instncias 11
bem como importaes globais de todo o package, tal como em:
import java.util.*;
A clusula de importao import java.lang.*; automaticamente assumida pela JVM, pelo que
est sempre implcita em qualquer programa JAVA. No h, pois, a necessidade de a escrever quando se
pretende importar todo o package.
Se ao definirmos uma dada classe pretendermos que esta v fazer parte de um dado package j existente,
ento a primeira declarao a fazer no ficheiro fonte a indicao do package a que a mesma vai pertencer,
conforme em:
package java.minhasClasses;
package jogos.classes;
No entanto, h que ter o cuidado adicional de acrescentar varivel de ambiente de nome CLASSPATH (ver
seco do captulo 2 sobre a instalao do JDK) os identificadores dos directrios onde tais classes devem
ser procuradas pelo interpretador.
Finalmente, todas as classes que no possuam qualquer referncia ao package de que vo fazer parte so
colocadas pelo compilador num package particular que se designa por package por omisso (default) e que
automaticamente associado ao directrio actual de trabalho, desde que na varivel CLASSPATH tal caminho
seja referenciado atravs do smbolo ..
Continuando agora com a definio da classe Ponto, resta-nos codificar o mtodo que determina se um
ponto simtrico, ou seja, se as suas coordenadas so iguais em valor absoluto. Ora, o mtodo que determina
o valor absoluto de um qualquer valor numrico encontra-se implementado na classe java.lang.Math, e
pode ser invocado usando Math.abs() (no pois um mtodo de instncia normal, tratando-se de um
mtodo especial a explicar mais tarde), lendo-se, o mtodo abs() da classe Math. O cdigo do nosso
mtodo simetrico() ser ento o seguinte:
boolean simetrico() { return Math.abs(x) == Math.abs(y); }
Note-se, portanto, que este mtodo especial abs() foi invocado utilizando um prefixo, que o identificador
da classe a que pertence, e no obedece ao padro normal de PPO que consiste no envio de uma mensagem a
um objecto receptor. Trata-se, pois, seguramente, de uma excepo que ser explicada posteriormente mas
que foi necessria aqui, pois foi necessrio recorrer a um servio definido na classe Math, como muitos
outros h em JAVA em muitas outras classes.
No exemplo, este servio prestado pela classe Math consistiu em permitir-nos invocar uma das suas muitas
funes matemticas, abs(int x), (cf. f(x)), que nos devolve um resultado. No h mensagem, no h
receptor. No h PPO. H apenas servios auxiliares que se encontram disponveis numa determinada classe
e que podem ser invocados.
Estas classes no servem para criar instncias pois no possuem tal capacidade, acabando por se comportar
como mdulos que implementam facilidades atravs dos seus mtodos.
3.2.7 Definio actual da classe Ponto
class Ponto {
// Construtores
Ponto() { x = 0; y = 0; }
Ponto(int cx, int cy) {
x = cx; y = cy;
}
// Variveis de Instncia
int x;
int y;
// Mtodos de Instncia
// interrogador devolve X
int getx() { return x; }
J JA AV VA A5 5 E E P PR RO OG GR RA AM MA A O O P PO OR R O OB BJ JE EC CT TO OS S ( (F F. . M M R RI IO O M MA AR RT TI IN NS S 2 20 00 06 6) )
12 Classes e Instncias
// interrogador devolve Y
int gety() { return y; }
// modificador incremento das Coordenadas
void incCoord(int deltaX, int deltaY) {
x = x + deltaX; y = y + deltaY;
}
// modificador decremento das Coordenadas
void decCoord(int deltaX, int deltaY) {
x -= deltaX; y -= deltaY;
}
/* determina se um ponto tem ambas as
coordenadas positivas */
boolean coordPos() {
return x > 0 && y > 0 ;
}
/* determina se um ponto simtrico, ou seja
se dista igualmente do eixo dos X e dos Y */
boolean simetrico() {
return Math.abs(x) == Math.abs(y);
}
}
3.2.8 Regras de acessibilidade a uma classe
JAVA fornece mecanismos de controlo de acesso (ou visibilidade) quer para os packages, que contm
conjuntos de classes, quer para as classes individuais, quer para cada um dos membros destas, como sejam
as variveis e os mtodos que nestas so definidos, quer ainda para outras construes a introduzir
posteriormente, tais como as Classes Abstractas e as Interfaces. Estes mecanismos de controlo de acesso
especificam quem tem acesso s entidades definidas.
So quatro os tipos de acesso (ou de visibilidade) que podem ser especificados em JAVA para estas
entidades, dos quais trs usando palavras reservadas que se designam por modificadores de acesso,
especificamente: public, protected e private. O quarto tipo de acesso definido por omisso, ou seja,
caso nenhum modificador seja declarado, conforme no exemplo da classe Ponto, tal como at aqui a
definimos, e designa-se por acesso de nvel package.
Em qualquer dos casos, o modificador de acesso , em geral, especificado antes de qualquer outra
especificao da entidade, seja ela classe, varivel ou mtodo, ou seja, no incio da sua declarao.
Na Tabela 3.1 sintetizam-se as regras de acesso ou visibilidade associadas a cada modificador de acesso para
as classes.
Modificador Acessvel a partir do cdigo de
public Qualquer classe
protected (*)
private (*)
nenhum
Classes dentro do seu package
Tabela 3.1 Modificadores de acesso para classes
Classes do tipo private e protected so, em JAVA, classes especiais (*inner classes) que so usadas na
implementao de classes predefinidas complexas de JAVA, algumas das quais sero referidas mais adiante
neste livro. Estas classes so definidas no interior de outras classes, implementando funcionalidades
especiais (ver captulo 11).
A classe Ponto anteriormente definida, dado no ter sido declarada usando um modificador particular, estar
acessvel apenas dentro do respectivo package. Porm, no declarmos a que package que esta vai
pertencer. Em tal situao, JAVA associa tal classe a um package particular sem identificador, o que se torna
C CC C C CC CL LL LL LL LA AA AA AA AS SS SS SS SS SS SS SS SE EE EE EE ES SS SS SS S E EE EE EE E I II I I II IN NN NN NN NS SS SS SS ST TT TT TT T N NN NN NN NC CC CC CC CI II II II IA AA AA AA AS SS SS SS S
Classes e Instncias 13
conveniente numa fase de desenvolvimento e teste da classe, dado que, em tal caso, o cdigo pode ser
interpretado a partir do directrio corrente.
No entanto, se pretendermos associar uma dada classe a um package, ento temos que usar uma declarao
de package, devendo esta ser a primeira linha de cdigo do programa. Por exemplo, se pretendssemos
declarar que a classe Ponto depois de compilada dever fazer parte do package java.classes1, cujo
directrio dever fazer parte da CLASSPATH, ento, escreveramos no nicio do ficheiro de definio da
classe Ponto:
package java.classes1;
class Ponto {
Se, adicionalmente, pretendssemos, tal como deve ser feito em geral, tornar a classe pblica, ento,
acrescentaramos o respectivo modificador de acesso antes da palavra reservada class, tal como em:
package java.classes1;
public class Contador {
3.2.9 Regras de acesso a variveis e
mtodos de instncia
A acessibilidade a variveis e mtodos de instncia de uma dada classe para cada tipo de modificador de
acesso , como se pode verificar pela tabela a seguir, exactamente igual. No entanto, as regras para a
aplicao de tais modificadores so completamente diferentes para cada caso.
Modificador Acessvel a partir do cdigo de
public Qualquer classe
protected
Prpria classe, qualquer classe do mesmo package e
qualquer subclasse
private Prpria classe
nenhum
Prpria classe e classes dentro do mesmo package
Tabela 3.2 Modificadores de acesso para variveis e mtodos
As variveis de instncia de uma dada classe podem ser declaradas de tal forma que nenhum cdigo, a no
ser o cdigo dos mtodos de instncia da classe onde a varivel declarada, se lhes pode referir, ou seja,
podem ser tornadas variveis de acesso restrito ao cdigo existente dentro da classe.
Para tal, como se pode ver pela tabela acima, bastar que na declarao da varivel se use o modificador
private, como as formas sintcticas do exemplo seguinte:
private double raio;
private String nome;
private int x;
Tal implica tambm, que exemplos anteriormente referidos de m programao so imediatamente
eliminados, pois expresses, tais como cx = p1.x; usadas exteriormente classe onde x declarada,
passam agora a dar mesmo um erro de compilao. Note-se que em C++, por exemplo, as variveis de
instncia so, por omisso, privadas.
Ao garantir o total encapsulamento da sua estrutura de dados interna classe (data hiding), o programador
ter agora que garantir, atravs de adequados mtodos de consulta e de modificao, que os clientes de tal
classe possuem uma API que lhes permita consultar e alterar o estado interno dos objectos criados.
Quanto aos mtodos de instncia, em geral passa-se exactamente o contrrio. De facto, eles so escritos para
que do exterior possam estar acessveis aos clientes de tal classe, ou seja, a todas as classes que pretendam
usar a classe criando instncias e realizar com estas computaes invocando os seus mtodos atravs de
mensagens. Portanto, e em geral, mtodos de instncia so de tipo de acesso public. A API (Application
J JA AV VA A5 5 E E P PR RO OG GR RA AM MA A O O P PO OR R O OB BJ JE EC CT TO OS S ( (F F. . M M R RI IO O M MA AR RT TI IN NS S 2 20 00 06 6) )
14 Classes e Instncias
Programming/Programmers Interface) de uma classe de JAVA o conjunto dos seus mtodos de instncia
com acesso public. A estes devemos adicionar os construtores, que devem igualmente ser public para que
as outras classes lhes tenham acesso, e assim possam invoc-los para criar instncias desta.
Os mtodos de instncia definidos como private, sendo apenas acessveis ao cdigo da prpria classe,
acabam por poder ser vistos como mtodos auxiliares, que por vezes tornam mais simples a codificao de
mtodos de instncia mais complexos, realizando clculos intermdios, suboperaes, etc.
Finalmente, as variveis declaradas dentro dos mtodos so variveis locais, sendo acessveis apenas a estes
e deixando de ter existncia quando tais mtodos terminam a sua execuo. Variveis declaradas dentro de
blocos { .} existem apenas dentro destes.
As regras de acessibilidade agora introduzidas levam-nos a ter que reescrever de forma mais correcta a classe
Ponto que desenvolvemos. A classe deve ser uma classe pblica, tal como pretendemos que sejam pblicos
os seus construtores. As variveis de instncia devem ser, portanto, declaradas como private, e os
respectivos mtodos selectores e modificadores definidos como public tambm.
Estas vo ser, em geral, as formas de acesso mais comuns aos membros das nossas classes. Construtores
public, variveis de instncia private e mtodos public.
3.2.10 Definio final da classe Ponto
public class Ponto {
// Construtores
public Ponto() { x = 0; y = 0; }
public Ponto(int cx, int cy) { x = cx; y = cy; }
//
// Variveis de Instncia
private int x;
private int y;

// Mtodos de Instncia
// interrogador devolve X
public int getx() { return x; }
// interrogador devolve Y
public int gety() { return y; }
// modificador incremento das Coordenadas
public void incCoord(int deltaX, int deltaY) {
x = x + deltaX; y = y + deltaY ;
}
// modificador decremento das Coordenadas
public void decCoord(int deltaX, int deltaY) {
x -= deltaX; y -= deltaY;
}
/* determina se um ponto tem ambas as
coordenadas positivas */
public boolean coordPos() {
return x > 0 && y > 0 ;
}
/* determina se um ponto simtrico, ou seja
se dista igualmente do eixo dos X e dos Y */
public boolean simetrico() {
return Math.abs(x) == Math.abs(y) ;
}
}
C CC C C CC CL LL LL LL LA AA AA AA AS SS SS SS SS SS SS SS SE EE EE EE ES SS SS SS S E EE EE EE E I II I I II IN NN NN NN NS SS SS SS ST TT TT TT T N NN NN NN NC CC CC CC CI II II II IA AA AA AA AS SS SS SS S
Classes e Instncias 15
Neste exemplo, no houve a necessidade de usar mtodos do tipo private. No entanto, este tipo de
mtodos, apenas acessveis dentro da prpria classe, devem ser vistos como mtodos puramente auxiliares
definio da classe, logo, sem qualquer interesse para o exterior. Por tal motivo no fazem parte da API da
classe.
3.2.11 Compilao e teste da classe Ponto
A compilao da classe Ponto, depois de o cdigo fonte ter sido introduzido num ficheiro de texto tipo
WordPad ou NotePad, e gravado como Ponto.java, consistir da invocao do compilador de JAVA na linha
de comandos, usando a seguinte forma:
javac [-opes] Ponto
A classe Ponto no uma classe por si s executvel (tal como qualquer outra deste tipo), pois no possui
um mtodo main(). Por isso, vamos agora estudar qual a forma usual de, em JAVA, se desenvolver cdigo
executvel para testar uma dada classe acabada de desenvolver, neste nosso exemplo, a classe Ponto.
Para tal, em JAVA, criada uma classe muito especial que ir servir para testar a classe desenvolvida. Esta
classe particular de JAVA vai assumir o papel do que noutras linguagens se designa por programa
principal. Porm, e por questes de simplicidade, o cdigo da classe de teste no apresentar qualquer
interaco com o utilizador para leitura de dados, mas apenas entre a classe de teste e a classe a testar atravs
da invocao dos mtodos desta atravs de parmetros constantes.
Ou seja, pretendemos desenvolver uma classe de teste da classe Ponto que nos permita criar instncias de
Ponto, enviar a estas instncias mensagens que correspondem invocao e execuo dos mtodos da sua
API, consultando e modificando o estado interno de tais instncias e podendo observar no monitor os
diversos resultados produzidos pelo envio de tais mensagens (introduziremos adiante o ambiente BlueJ que
muito nos facilitar esta e outras tarefas).
Esta classe, criada apenas com o objectivo de testar uma dada classe desenvolvida, tem algumas
caractersticas particulares que devemos agora descrever e analisar.
Em primeiro lugar, e tal como a classe em desenvolvimento e teste, esta classe no deve estar associada a
qualquer package particular, mas antes ao package por omisso, que associado ao directrio corrente.
Sendo, em geral, de acesso pblico, esta classe tem a seguinte estrutura de definio genrica:
public class TestePonto {
// Classe de teste da Classe Ponto.
// Aqui se escrevem variveis globais e
// mtodos auxiliares.
public static void main(String args[]) {
/* Aqui se escreve todo o cdigo de teste, ou seja,
de criao de instncias, de envio de mensagens,
de apresentao de resultados, etc. */
}
}
Tal mtodo tem que ter o nome main e o atributo static, cujo significado ser mais frente explicado,
dado que o interpretador de JAVA, ao ser invocado sobre uma qualquer classe, inicia a execuo
exactamente pelo mtodo declarado como static main().
Ainda que de momento no possa ser completamente definido o significado do atributo static, esta a
estrutura a construir para a criao de uma classe JAVA que tenha por objectivo servir como classe de teste
da camada computacional das classes definidas pelo utilizador, usando sempre apenas as API
disponibilizadas por tais classes.
O mtodo main() de cada classe de teste, vai conter, fundamentalmente, cdigo no interactivo de criao
J JA AV VA A5 5 E E P PR RO OG GR RA AM MA A O O P PO OR R O OB BJ JE EC CT TO OS S ( (F F. . M M R RI IO O M MA AR RT TI IN NS S 2 20 00 06 6) )
16 Classes e Instncias
de instncias, de envio de mensagens s instncias criadas e cdigo de apresentao de resultados das
consultas s instncias, cdigo de output que escrito usando as instrues bsicas System.out.print(),
ou println(), ou printf() para escrita no ecr.
public class TestePonto {
// Classe de teste da Classe Ponto.
public static void main(String args[]) {
// Criao de Instncias
Ponto pt1, pt2, pt3;
pt1 = new Ponto();
pt2 = new Ponto(2, -1);
pt3 = new Ponto(0, 12);

// Utilizao das Instncias
int cx1, cx2, cx3; // variveis auxiliares
int cy1, cy2, cy3; // variveis auxiliares
cx1 = pt1.getx();
cx2 = pt2.getx();

// sada de resultados para verificao
System.out.println("cx1 = " + cx1);
System.out.println("cx2 = " + cx2);

// alteraes s instncias e novos resultados

pt1.incCoord(4,4); pt2.incCoord(12, -3);
cx1 = pt1.getx(); cx2 = pt2.getx();
cx3 = cx1 + cx2;
System.out.println("cx1 + cx2 = " + cx3);

pt3.decCoord(10, 20); pt2.decCoord(5, -10);
cy1 = pt2.gety(); cy2 = pt3.gety();
cy3 = cy1 + cy2;
System.out.println("cy1 + cy2 = " + cy3);
}
}
3.2.12 Mtodos complementares usuais
Vamos agora complementar a definio da classe Ponto com mtodos que, no tendo sido pedidos na lista
de requisitos, so mtodos de implementao quase obrigatria, e que so os mtodos que permitem
determinar a igualdade de dois pontos, criar uma cpia no partilhada de um ponto e criar uma representao
textual (sob a forma de caracteres ASCII/UTF) de um ponto.
O mtodo igual() dever permitir comparar o objecto parmetro com o receptor e devolver um valor
boleano, true ou false, conforme estes sejam ou no iguais em valor (que no em identidade, que
corresponde ao seu endereo). O mtodo igual(), por razes bvias, deve obedecer seguinte assinatura e
resultado:
boolean igual(Ponto p)
ou seja, receber como parmetro uma instncia da classe Ponto, verificar se o parmetro no uma
referncia nula, e, caso no seja, implementar a igualdade de objectos desta classe Ponto, sob a forma de
uma relao de equivalncia (ou seja, sendo reflexiva, simtrica, transitiva e consistente).
Teramos o seguinte cdigo para comparao de instncias da classe Ponto:
public boolean igual(Ponto p) {
if (p != null) return (x == p.getx()) && (y == p.gety());
else return false;
}
C CC C C CC CL LL LL LL LA AA AA AA AS SS SS SS SS SS SS SS SE EE EE EE ES SS SS SS S E EE EE EE E I II I I II IN NN NN NN NS SS SS SS ST TT TT TT T N NN NN NN NC CC CC CC CI II II II IA AA AA AA AS SS SS SS S
Classes e Instncias 17
ou, ainda:
public boolean igual(Ponto p) {
return (p == null) ? false : x == p.getx() &&
y == p.gety();
usando o operador condicional ternrio ?:.
Em primeiro lugar, a condio garante que apenas iremos comparar os valores da instncia parmetro com o
receptor se o objecto parmetro no tiver o valor null, ou seja, se p != null. Satisfeita esta condio,
ento poderemos comparar os valores das duas instncias de Ponto, parmetro e receptor, comparando os
valores das respectivas coordenadas, o que corresponde comparao de dois inteiros usando o respectivo
operador de igualdade ==.
O mtodo copia() dever permitir criar e devolver uma cpia do objecto receptor da mensagem copia(),
devendo ser original e cpia garantidamente objectos diferentes, ou seja, devendo-se garantir que, o original
e a cpia no so o mesmo objecto, so instncias da mesma classe e tm o mesmo valor.
O mtodo copia() deve ter como assinatura Ponto copia(), vai ser usado em expresses como Ponto
p2 = p1.copia(); e tem o cdigo seguinte:
// Cria um ponto que uma cpia do receptor
public Ponto copia() {
return new Ponto(x, y);
}
Utilizou-se o construtor passando-lhe os valores das variveis de instncia do receptor, garantindo assim que,
qualquer que seja o receptor da mensagem copia(), uma nova instncia de Ponto criada contendo os
mesmos valores do receptor, mas sendo distinta deste pois no partilha o seu endereo (deep copy).
Note-se que em JAVA a passagem de parmetros para os mtodos se faz de duas formas distintas: por valor
(ou cpia) para os tipos simples e por referncia (endereo) para os tipos referenciados (objectos ou arrays).
De notar que o resultado devolvido por um mtodo de JAVA obedece igualmente a tal mecanismo, pelo que
h que ter sempre cuidado com o que passamos para o exterior como resultado de um mtodo. Se passarmos
para o exterior como resultado uma varivel de instncia que um objecto, o que estamos de facto a passar
um apontador para esse objecto, dando-se assim acesso para a sua manipulao a partir do exterior da classe.
Logo, se assim procedermos, como estarmos a enviar de "Tria" para fora "cavalos de Tria" para
"entrarem em Tria", sendo ns prprios a violar o encapsulamento. Que fazer em casos destes? Simples:
criar uma cpia da varivel de instncia e devolver como resultado a cpia realizada (de facto, o seu
endereo) e nunca a varivel de instncia.
Um outro mtodo, que muito usual associar-se a qualquer classe como mtodo de instncia, um mtodo
que d como resultado uma representao textual da instncia, para, eventualmente, ser posteriormente
apresentada em ecr ou gravada num ficheiro de texto de forma formatada.
Este mtodo, a que vamos dar o nome de paraString(), vai converter para caracteres cada uma das
variveis de instncia, dar-lhes um formato legvel e construir uma instncia da classe String como
resultado. Vejamos um exemplo com a classe Ponto:
public String paraString() {
String s = new String();
s = "Ponto(" + x + ", " + y + ")";
return s;
}
ou, de forma mais simples mas equivalente,
public String paraString() { return "Pt(" + x + ", " + y + ")"; }

J JA AV VA A5 5 E E P PR RO OG GR RA AM MA A O O P PO OR R O OB BJ JE EC CT TO OS S ( (F F. . M M R RI IO O M MA AR RT TI IN NS S 2 20 00 06 6) )
18 Classes e Instncias
A classe String tambm uma classe do package java.lang que fornece um conjunto de mtodos para a
manipulao de strings de caracteres, para alm de possuir (herdados da linguagem C e de outras) um
conjunto de operadores usuais, tais como o operador de concatenao de strings + usado acima. Este
operador permite mesmo concatenar a uma string valores de tipos primitivos depois de os converter
automaticamente para strings , como em "Ponto(" + x .
Objectos do tipo String podem ser criados no s usando new String() mas tambm, excepcionalmente,
atravs de atribuio directa de um valor, como em:
String nome1, nome2, linhas;
nome1 = "Pedro Nuno";
nome2 = new String("Rita Isabel");
String linhas = nome1 + "\n" + nome2;
O teste de igualdade entre duas strings realizado, naturalmente, atravs da comparao dos seus caracteres
e no dos seus endereos (cf. ==), da que nunca se deva confundir os dois casos. O mtodo que verifica se
duas instncias da classe String so iguais designa-se por equals(), recebe uma string como parmetro e
devolve um boleano:
boolean ok, iguais;
ok = nome1.equals(nome2);
iguais = nome1.equals(nome2) && nome2.equals(nome3);
As strings de JAVA possuem no entanto um grande inconveniente que em certas circunstncias pode mesmo
conduzir a grandes perdas de performance quando se programam aplicaes de maior escala. As strings de
JAVA, depois de criadas, so imutveis (so entidades constantes em memria). Por isso, quando por
exemplo escrevemos a frase nome1 + " da Silva Costa", o que acontece que uma terceira string vai
ser criada em memria para guardar os caracteres resultantes da concatenao destas duas, e assim,
sucessivamente, a cada concatenao ou atribuio do tipo nome1 = nome1 + "\n".
Imagine-se, portanto, o esforo de alocao de memria que frases aparentemente simples como a que antes
escrevemos no mtodo paraString() implicam, e o consequente peso na eficincia dos programas.
Havendo em todo o caso que usar o tipo String em mltiplas situaes, apresentam-se na tabela seguinte
alguns dos mtodos mais teis.

Mtodo Semntica
char charAt(int i) Carcter no ndice i
int compareTo(String s)
-1 menor, 0 igual, 1 maior que a string
parmetro
boolean endsWith(String s) s prefixo da receptora?
boolean equals(String s) Igualdade de strings
String String.valueOf(simples) Converte para string
int length() Comprimento
String substring(int i, int f) Substring entre i e f
String toUpperCase() Converte para maisculas
String toLowerCase() Converte para minsculas
String trim() Remove espaos (incio e fim)
Tabela 3.3 Alguns mtodos da classe String
Salvo as raras excepes em que tal perda de performance seja negligencivel, ao longo deste livro
utilizaremos as classes StringBuilder e StringBuffer, que criam instncias de strings que so
dinmicas e disponibilizam mtodos mais do que suficientes para a manipulao destas, sempre que tivermos
que criar strings resultantes da juno de vrias substrings (como no mtodo paraString() e outros).
3.2.13 Sobrecarga de mtodos: overloading
A sobrecarga semntica (overloading) de operadores, ou seja, a possibilidade de o mesmo operador possuir
significados distintos em funo das entidades sobre quem opera num dado momento (ex.: o que significa x1
C CC C C CC CL LL LL LL LA AA AA AA AS SS SS SS SS SS SS SS SE EE EE EE ES SS SS SS S E EE EE EE E I II I I II IN NN NN NN NS SS SS SS ST TT TT TT T N NN NN NN NC CC CC CC CI II II II IA AA AA AA AS SS SS SS S
Classes e Instncias 19
+ x2 na maioria das normais linguagens de programao?) uma daquelas idiossincrasias das linguagens,
que so por vezes contestadas mas que at do algum jeito ter disponveis.
Em JAVA e na maioria das linguagens de PPO, existe tambm a possibilidade de se usar sobrecarga
semntica de mtodos (method overloading), que consiste no facto de se poderem definir na mesma classe
dois ou mais mtodos com o mesmo nome desde que tenham assinaturas diferentes. Por assinaturas
diferentes dever-se- entender uma lista de parmetros diferente, seja quanto aos seus tipos de dados ou
quanto ordem dos mesmos.
Para alm dos mtodos de instncia, os construtores esto sempre em sobrecarga dado serem obrigados a ter
um nome igual ao da prpria classe. Tal sobrecarga, como vimos, no entanto muito til pois so em geral
mltiplas as formas como pretendemos criar instncias de uma dada classe.
Relativamente aos mtodos de instncia, dado que a activao de cada mtodo realizada em funo da
estrutura da mensagem recebida, o nome, nmero, tipo e ordem dos parmetros da mensagem sero a
chave para a determinao do mtodo a executar, pelo que o seu identificador apenas um token de tal
chave.
Assim, na classe Ponto anterior, para alm dos dois mtodos modificadores que incrementavam ambas as
coordenadas, cf.
public void incCoord(int deltaX, int deltaY)
public void decCoord(int deltaX, int deltaY)
poderamos acrescentar, ainda que sem vantagens especiais neste caso, os mtodos que incrementam e
decrementam X e Y de apenas 1 unidade, por exemplo
public void incCoord()
public void decCoord()
ou um paraString() em que o incio do texto fosse dado como parmetro:
public String paraString(String txtHeader)
Enfim, muitos outros exemplos poderiam ser encontrados, sendo certo que a sobrecarga de mtodos tanto
mais til quanto mais complexos e/ou interessantes forem as classes a desenvolver.
3.2.14 Mtodos com nmero varivel de parmetros
Muitas das vezes, a sobrecarga de mtodos realizada, apenas porque pretendemos ter mtodos com o
mesmo nome, com parmetros do mesmo tipo, mas tendo um nmero diferente destes.
Consideremos que se pretende implementar um mtodo que, dados dois, trs, quatro ou mais nmeros
inteiros, e um factor multiplicativo que um valor real, calcule o somatrio das multiplicaes. A primeira
soluo poderia ser criar mtodos baseados em sobrecarga, que tratassem cada um dos casos, como em:
public double imposto(double taxa, int val1, int val2) {
return val1*taxa + val2*taxa;
}
public double imposto(double taxa, int val1, int val2,
int val3) {
return val1*taxa + val2*taxa + val3*taxa;
}
Esta soluo , porm, pouco verstil, pois obriga-nos a contar previamente quantos nmeros vamos somar,
para invocarmos o mtodo adequado. Assim, o usual nestas circunstncias seria criarmos um array de
inteiros, preench-lo, e depois pass-lo como parmetro para um nico mtodo que, recebendo o array,
calculasse o somatrio dos resultados dos produtos, como em:
public double imposto(double taxa, int[] vals) {
double impTotal = 0.0;
for(int i = 0; i < vals.length; i++)
J JA AV VA A5 5 E E P PR RO OG GR RA AM MA A O O P PO OR R O OB BJ JE EC CT TO OS S ( (F F. . M M R RI IO O M MA AR RT TI IN NS S 2 20 00 06 6) )
20 Classes e Instncias
impTotal += vals[i]*taxa;
return impTotal;
}
Em JAVA5, foram introduzidos mtodos especiais que aceitam um nmero varivel de argumentos
(varargs). Neste mtodos, que podem ter parmetros normais, o parmetro que pode ser substitudo por um
nmero indeterminado de argumentos especificado escrevendo-se o seu tipo e nome, tal como em:
public imposto(double taxa, int... vals) {
Como nunca sabemos qual o efectivo nmero de valores que foram dados como argumentos, ento teremos
agora o problema de saber como percorrer todos os valores dados como argumentos do mtodo. Ora, o ciclo
foreach foi adaptado para contemplar este tipo de situao, permitindo percorrer automaticamente os
argumentos.
No nosso exemplo teramos ento como cdigo final:
public imposto(double taxa, int... vals) {
double impTotal = 0.0;
for(int val : vals) impTotal += val;
return impTotal;
}
A utilizao deste mtodo, apresentar as seguintes formas exemplo:
double calc1 = 0.0, calc2 = 0.0;
calc1 = imposto(0.45, 12, 34, 44, 25);
calc2 = imposto(0.21, 56, 34, 11, 23, 45, 2, 45, 67);
Os argumentos podem ser tambm de tipo referenciado, em cujo caso o seu tipo dever ser o identificador da
classe (ou compatvel) dos argumentos. Por exemplo, poderamos ter como argumentos instncias de Ponto,
num mtodo com varargs para calcular o ponto com maior coordenada em X, como se mostra no cdigo
seguinte:
public Ponto maiorX(Ponto... pts) {
Ponto max = new Ponto(-9999, -9999);
for(Ponto p : pts)
if (p.getx() > max.getx()) max = p;
return max.copia();
}
O mtodo poderia, ento, ser agora utilizado da forma seguinte:
Ponto maxP1 = maiorX(new Ponto(-5,3), new Ponto(0,0));
Ponto maxP2 = maiorX(p1, p2, p3, p4, p5);
Completmos assim o primeiro ciclo de conhecimentos necessrios criao de classes em JAVA, ficando a
conhecer alguns dos seus mais importantes membros, como as variveis e os mtodos de instncia e como
podemos impor, atravs dos modificadores de acesso, regras para a sua utilizao.
Em seguida, vamos ver como que as classes podem ser usadas na criao de outras classes, ou seja, como
podemos criar classes reutilizando o cdigo j desenvolvido em classes anteriormente definidas.
3.3 Composio na
definio de classes
A classe Ponto cuja definio nos tem servido de exemplo para a introduo de um conjunto de conceitos
importantes, , em si, uma classe muito simples, dado que a definio das variveis de instncia foi realizada
recorrendo apenas a um tipo simples, no exemplo, o tipo int.
C CC C C CC CL LL LL LL LA AA AA AA AS SS SS SS SS SS SS SS SE EE EE EE ES SS SS SS S E EE EE EE E I II I I II IN NN NN NN NS SS SS SS ST TT TT TT T N NN NN NN NC CC CC CC CI II II II IA AA AA AA AS SS SS SS S
Classes e Instncias 21
Possuindo JAVA, como sabemos j, um enorme conjunto de classes predefinidas s quais se podem juntar as
nossas prprias classes, poder agora perguntar-se de que forma umas e outras podem ser usadas na
definio de uma nova classe.
Em JAVA, tal como em qualquer outra linguagem de PPO, existe um mecanismo bsico e simples de uma
classe poder usar na sua definio classes j definidas, o que corresponde a um primeiro mecanismo de
reutilizao, mecanismo que se designa por composio ou agregao. Este mecanismo de composio
consiste na possibilidade de as variveis de instncia definidas numa classe poderem ser definidas como
sendo de um tipo correspondente a classes j existentes, sendo depois manipuladas usando todos os mtodos
definidos nas suas classes tipo. Apenas teremos que conhecer as API e enviar as mensagens que activam os
mtodos compatveis com os tipos de tais variveis.
Naturalmente que, sendo este mecanismo bastante favorvel, porque vem facilitar a reutilizao, deve desde
j tambm referir-se que uma utilizao optimizada do mesmo implica um bom conhecimento de todas as
classes existentes, no tanto das suas implementaes, mas, seguramente, das suas API.
At agora, o nico relacionamento que vislumbramos entre classes foi um simples relacionamento do tipo A
invocou mtodo de B. Na classe Ponto, tivemos a necessidade de invocar mtodos da classe
java.lang.Math, pelo que, podemos afirmar que a nossa classe Ponto usa Math.
No entanto, o mecanismo de composio estabelece um relacionamento entre classes de natureza mais
forte, que uma relao de incluso. Se a classe A contm (has) objectos da classe B, dado que algumas
das suas variveis de instncia so instncias do tipo B, ento a classe A diz-se que composta por B. De B
dir-se- que parte (da definio) de A (part-of). Por exemplo, Motor, Asa, Passageiro, Piloto, etc.,
todas podem ser classes que podero fazer parte da composio de uma classe Aviao.
Um exemplo simples desta composio (ou agregao) usando a classe Ponto, seria a criao de uma classe
Circulo, cujas instncias fossem definidas como tendo um centro dado por uma instncia da classe Ponto
e um raio dado por um double. Poderamos ter a seguinte definio estrutural de tal classe:
public class Circulo {
// construtores
. . . . . . .
// variveis de instncia
private Ponto centro;
private double raio;
...................
}
Vamos, agora, criar uma classe que defina segmentos de recta para tal contando com a nossa anteriormente
definida classe Ponto para caracterizar a estrutura do segmento de recta, usando dois pontos delimitadores
do segmento. Note-se, como primeira diferena relativamente classe Ponto, que agora temos variveis de
instncia que no so de tipos simples mas de tipos referenciados (objectos), pelo que as questes de
inicializao dos seus valores so diferentes.
Vamos considerar, por hiptese, que crivamos a classe Segmento sem definir qualquer construtor. Ser que
podamos criar instncias desta classe? E com que valores seriam ento as variveis de instncia destas
inicializadas?
public class Segmento {
// Variveis de Instncia
private Ponto p1; private Ponto p2;
...
}
A resposta primeira questo sim, tal como vimos j anteriormente. Em JAVA, se uma classe for definida
sem ter definido qualquer construtor, -lhe acrescentado de imediato o construtor por omisso:
public NomeClasse() {}
J JA AV VA A5 5 E E P PR RO OG GR RA AM MA A O O P PO OR R O OB BJ JE EC CT TO OS S ( (F F. . M M R RI IO O M MA AR RT TI IN NS S 2 20 00 06 6) )
22 Classes e Instncias
A questo seguinte saber-se quais os valores iniciais que este construtor atribui s variveis de instncia.
Vimos anteriormente que s variveis de tipos simples lhes so atribudos os valores predefinidos desses
tipos (0 para int, 0.0 para double, false para boolean, etc.).
Em JAVA, as variveis de instncia de tipos referenciados so por omisso inicializadas com o valor null
(Figura 3.3).
null
null
null
null
p1
p2
segm1

Figura 3.3 Inicializao de variveis de instncia-objecto por omisso
No entanto, ser sempre melhor prtica que sejamos ns a definir construtores que atribuam valores iniciais
no null s variveis de instncia das classes que criamos.
Teremos, ento, para a classe Segmento os seguintes construtores:
public class Segmento {
// Construtores
public Segmento() {
p1 = new Ponto(); p2 = new Ponto();
}
public Segmento(Ponto pa, Ponto pb) {
p1 = pa; p2 = pb;
}
// Variveis de Instncia
private Ponto p1;
private Ponto p2;
...................
}
Para completarmos a classe Segmento vamos agora definir, para alm dos mtodos interrogadores e
modificadores, e os mtodos para igualdade, copia() e paraString(), mtodos que realizem as seguintes
operaes:
Dar como resultado o comprimento do segmento;
Dar como resultado o declive do segmento;
O comprimento de um segmento de recta dado pela expresso seguinte:

2 2
y2) - (y1 x2) - (x1 +
da qual poder resultar um nmero real, pelo que o mtodo dever devolver um resultado do tipo double e
invocar a funo matemtica sqrt() da classe Math (conforme nos revelaria a consulta API desta classe)
para calcular a raiz quadrada da expresso que se apresenta acima e que a soma do quadrado dos x com o
quadrado dos y:
public double compSeg() {
int dx = p1.getx() p2.getx();
int dy = p1.gety() p2.gety();
return Math.sqrt(dx*dx + dy*dy);
}
C CC C C CC CL LL LL LL LA AA AA AA AS SS SS SS SS SS SS SS SE EE EE EE ES SS SS SS S E EE EE EE E I II I I II IN NN NN NN NS SS SS SS ST TT TT TT T N NN NN NN NC CC CC CC CI II II II IA AA AA AA AS SS SS SS S
Classes e Instncias 23
O mtodo seguinte dever calcular o declive m = (y2-y1)/(x2-x1) do segmento, pelo que o resultado dever
ser igualmente um valor real.
// determina o declive da recta
public double declive() {
double dx = (double)(p1.getx() p2.getx());
double dy = (double)(p1.gety() p2.gety());
return dy/dx;
}
De notar que, sendo o resultado esperado um valor real e sendo as duas coordenadas valores inteiros, a sua
diferena um valor inteiro. A diviso (/) de dois inteiros d como resultado um inteiro e no um real.
Assim, devemos fazer o casting dos valores para double (real) antecipadamente operao de diviso,
para que se trate de uma diviso de dois nmeros reais com resultado real.
Crimos, portanto, uma classe designada Segmento composta por duas variveis de instncia da classe
Ponto e, respeitando a API definida em Ponto, trabalhmos com as respectivas variveis como se de tipos
primitivos se tratassem. A base do mecanismo de composio de classes exactamente que aquilo que
num dado momento parece estar a ser composto e, portanto, no era ainda primitivo, possa de seguida ser
material bsico de construo para o que houver a construir em seguida.
Criada a classe Segmento a partir de Ponto, podemos agora us-la para definir novas classes contendo
instncias de Segmento como suas variveis de instncia.
Vamos, ento, desenvolver um pequeno project, que, embora seja ainda do tipo monoclasse, se apresenta
com maior nmero de requisitos e que tem por objectivo alicerar em sede de projecto o conjunto de
conhecimentos que foram at agora transmitidos ao longo dos pequenos exemplos apresentados.
3.4 Exemplo: porta-
moedas multibanco
(PMMB)
Vamos agora desenvolver uma classe um pouco mais complexa, necessitando j de incorporar os
conhecimentos at aqui adquiridos, aos quais juntaremos mais alguns.
Trata-se de desenvolver uma classe cujas instncias so os pouco utilizados mas interessantes Porta Moedas
MultiBanco, possuindo as caractersticas seguintes:
Um PMMB tem um cdigo alfanumrico nico;
Um PMMB tem gravado o nome do titular;
Um PMMB ao ser criado tem saldo 0.0 ;
A qualquer momento possvel carregar o PMMB com X ;
Um pagamento apenas pode ser realizado se a importncia a pagar no ultrapassar o valor do saldo;
A qualquer momento dever ser possvel saber o saldo do PMMB;
Dever registar-se e poder consultar-se o nmero total de movimentos activos realizados, ou seja,
carregamentos e pagamentos;
Devem ser operaes tambm disponveis: igualdade de cartes (por nmero apenas), cpia e
representao como String.
Vamos comear por especificar a estrutura interna do PMMB, definindo um tipo para cada uma das variveis
de instncia: o cdigo, que at alfanumrico, ser, como usual, do tipo String; o nome do titular
igualmente uma String; o saldo do PMMB ser um double j que o valor um nmero real (ex.: ). O
nmero de movimentos ser um valor do tipo int.
Podemos, ento, desde j, definir os construtores e as variveis de instncia:

J JA AV VA A5 5 E E P PR RO OG GR RA AM MA A O O P PO OR R O OB BJ JE EC CT TO OS S ( (F F. . M M R RI IO O M MA AR RT TI IN NS S 2 20 00 06 6) )
24 Classes e Instncias
public class PMMB {
// Variveis de Instncia
private String codigo;
private String titular;
private double saldo;
private int numMovs; // total de movimentos
// Construtores
public PMMB() {
codigo = ""; titular = "";
saldo = 0.0; numMovs = 0;
}
public PMMB(String codigo, String tit,
double saldo, int numMovs)
this.codigo = codigo; titular = tit;
this.saldo = saldo; this.numMovs = numMovs;
}
}
Vamos, em seguida, definir os mtodos que vo ser tornados pblicos pela classe PMMB. Em primeiro lugar,
deveremos programar um conjunto de mtodos de acesso s variveis de instncia PMMB, mtodos que
sero os seguintes:
public String getCodigo() { return codigo; }
public String getTitular() { return titular; }
public int getSaldo() { return saldo; }
public int getNumMovs() { return numMovs; }
Vamos agora escrever o cdigo dos mtodos modificadores do estado, sabendo-se que os carregamentos e os
pagamentos devem no s alterar o saldo da conta mas tambm incrementar o nmero de movimentos da
mesma:
public void mudaTitular(String novoTit) {
titular = novoTit;
}

public void carregaPM(double valor) {
saldo = saldo + valor;
numMovs++;
}
3.4.1 Mtodos parciais e pr-condies
Deixmos propositadamente para o fim o mtodo pagamento, dado apresentar uma caracterstica particular
que, por ser muito comum em Informtica, merece uma anlise especial, por forma a ser de futuro
metodologicamente resolvida. De facto, a operao de pagamento de uma quantia uma operao
condicionada, ou seja, uma operao que nem sempre pode ser realizada com sucesso, sendo por vezes
impossvel a sua realizao. Qualquer que seja o PMMB, no dever nunca ser possvel realizar um
pagamento de uma importncia maior que o saldo actual do PMMB. Assim, apenas deveremos invocar a
operao de pagamento numa situao em que a operao possa de facto ser realizada com sucesso. Para tal,
deveremos realizar previamente um teste condio que determina se a operao pode ou no ser invocada.
Em geral, sempre que uma dada operao no total, isto , parcial, ou seja, no deve ser executada em
certas condies, a sua codificao sem qualquer apoio metodolgico torna o seu cdigo muito pouco claro.
Por um lado, porque se torna imperioso introduzir no prprio cdigo o teste de tais condies de erro bem
como o tratamento das mesmas, caso ocorram. Por outro lado, porque, em caso de erro, se torna necessrio
notificar o invocador de que a operao no pde ser executada.
Uma terrvel, ainda que muito usual, soluo a seguinte:
public void pagamento(double valor) {
if (saldo >= valor)
saldo = saldo valor;
C CC C C CC CL LL LL LL LA AA AA AA AS SS SS SS SS SS SS SS SE EE EE EE ES SS SS SS S E EE EE EE E I II I I II IN NN NN NN NS SS SS SS ST TT TT TT T N NN NN NN NC CC CC CC CI II II II IA AA AA AA AS SS SS SS S
Classes e Instncias 25
else
System.out.println("Saldo Insuficiente!");
}
A soluo parece pacfica, est bem estruturada, etc., mas vai contra vrios dos princpios fundamentais da
Engenharia de Software. Em primeiro lugar, o princpio da separao da camada computacional da camada
de input/output. Se estas duas camadas se misturarem, quando uma muda a outra ter que mudar.
Por exemplo, o cdigo do mtodo anterior no funciona se a aplicao for transferida para uma interface
grfica. Por outro lado, e pela mesma ordem de razes, o princpio do encapsulamento, que atrs referimos
como sendo a base de toda a PPO.
Um outro exemplo de uma m codificao deste mtodo poderia ser o cdigo seguinte (ou variantes
idnticas s com um return), que tambm bastante tpico:
// m codificao de um mtodo parcial
public boolean pagamento(double valor) {
if (saldo >= valor) {
saldo = saldo valor;
return true;
}
else
return false;
}
Em primeiro lugar, o tipo do resultado, que havamos definido como devendo ser void, j que se trata de um
modificador do estado, passou a ter que ser boolean, dado que se pretende que, externamente ao mtodo se
possa saber se a operao foi ou no bem sucedida. Claro que, do ponto de vista da clareza da assinatura do
mtodo em termos metodolgicos, torna-se muito pouco claro porque que um modificador do estado
devolve um boleano. Por outro lado, do ponto de vista do cdigo invocador deste mtodo, algumas
preocupaes adicionais tero que ser tomadas. De facto, dado que o mtodo devolve um boleano, no o
poderemos invocar usando a que seria a expresso normal caso o resultado fosse void:
meuPMMB.pagamento(10.50);
mas antes uma srie de expresses, tais como:
boolean ok = meuPMMB.pagamento(10.50); // teste
if(ok)
meuPMMB.pagamento(10.50); // compra !
else
System.out.println("Pagamento OFF !");
Claro que este cdigo, dado possuir instrues de sada, apenas poderia ser cdigo da classe de teste e no
cdigo de outro qualquer mtodo, o que faz levantar a questo de se saber como trataria a situao de erro
um mtodo de instncia de uma outra classe que tivesse invocado o mtodo pagamento. Provavelmente,
teria que alterar igualmente o seu tipo de resultado para poder comunicar a quem por sua vez o invocou, que
no cumpriu totalmente os seus objectivos, isto , que o servio que lhe foi solicitado falhou.
A questo metodolgica que est em causa saber se produzido melhor cdigo quando, como no exemplo
anterior, se invoca a operao em qualquer estado e, em seguida, se pergunta se tudo correu bem, e, caso no
tenha corrido, se informa quem a invocou de que afinal no o deveria ter feito (cf. mtodos teraputicos), ou
se, pelo contrrio, se deve testar antecipadamente se a operao pode ser invocada e, s se tal for possvel,
esta de facto invocada garantidamente com sucesso (cf. mtodos profilcticos).
Nesta segunda abordagem, comea-se por definir a condio prvia realizao de tal operao, designada
por pr-condio, que implementada num mtodo que deve ser public e que devolve como resultado um
boolean aps realizar o teste ao estado interno do objecto.

J JA AV VA A5 5 E E P PR RO OG GR RA AM MA A O O P PO OR R O OB BJ JE EC CT TO OS S ( (F F. . M M R RI IO O M MA AR RT TI IN NS S 2 20 00 06 6) )
26 Classes e Instncias
public boolean prePaga(double valor) {
return saldo >= valor ;
}
A seguir programa-se o cdigo do mtodo total, isto sem limitaes, dado que se sabe que, quando for
invocado, porque a pr-condio se verifica ( true), e que quem o vai usar j dever ter tido tal
preocupao (como um contrato entre cliente e servidor).
public void pagamento(double valor) {
saldo = saldo valor;
numMovs++;
}
Finalmente, no cdigo invocador, haver que perceber que a pr-condio deve ser testada antes de invocar
o mtodo, o que, admitindo que a varivel conta uma instncia de ContaBanc, se traduz na seguinte
estruturao:
if (meuPMMB.prePaga(val))
meuPMMB.pagamento(val); // realiza a operao
else
System.out.println("Levantam. impossvel !");
Se pr-condio tivssemos dado o nome sugestivo de podePagar?(val), ento poderamos dizer que
melhoria da clareza do cdigo do mtodo invocado se tinha adicionado clareza no cdigo do invocador. No
sendo rgida a atribuio de nomes s pr-condies, tal clareza facilmente alcanvel. Importante sim,
que estas pr-condies sejam declaradas como mtodos pblicos, e documentadas como sendo funes de
teste para a correcta invocao dos respectivos mtodos.
At ao estudo do mecanismo de excepes de JAVA, esta ser a metodologia de programao a adoptar para
mtodos parciais, isto , mtodos que apresentam restries de funcionamento.
Vamos de seguida apresentar o cdigo completo da classe PMMB, como sempre usando linhas de comentrio
para separar os vrios membros da classe, designadamente, os construtores, variveis de instncia e mtodos
de instncia. So adicionados classe os trs mtodos complementares que devem sempre ser
implementados numa classe, mesmo que tal no seja explicitamente pedido, designadamente, os mtodos
igual(), copia() e paraString().
public class PMMB {
// Construtores
public PMMB() {
codigo = ""; titular = "";
saldo = 0.0; numMovs = 0;
}
public PMMB(String codigo, String tit,
double sld, int nMovs) {
this.codigo = codigo; titular = tit;
saldo = sld; numMovs = nMovs;
}
// Variveis de Instncia
private String codigo; private String titular;
private double saldo;
private int numMovs; // total de movimentos
// Mtodos de Instncia
public String getCodigo() { return codigo; }
public String getTitular() { return titular; }
public double getSaldo() { return saldo; }
public int getNumMovs() { return numMovs; }
//
public void mudaTitular(String novoTit) {
titular = novoTit;
}

C CC C C CC CL LL LL LL LA AA AA AA AS SS SS SS SS SS SS SS SE EE EE EE ES SS SS SS S E EE EE EE E I II I I II IN NN NN NN NS SS SS SS ST TT TT TT T N NN NN NN NC CC CC CC CI II II II IA AA AA AA AS SS SS SS S
Classes e Instncias 27
public void carregaPM(double valor) {
saldo = saldo + valor; numMovs++;
}
public boolean prePaga(double valor) {
return saldo >= valor ;
}
public void pagamento(double valor) {
saldo = saldo valor; numMovs++;
}
//
public String paraString() {
StringBuilder s = new StringBuilder();
s.append("------- PMMB N: ");
s.append(codigo);
s.append("\nTitular: "); s.append(titular);
s.append("\nSaldo Actual: "); s.append(saldo);
s.append("\nMovimentos; "); s.append(numMovs);
s.append("\n--------------------------------");
return s.toString();
}
//
public boolean igual(PMMB pm) {
return codigo.equals(pm.getCodigo());
}
//
public PMMB copia() {
return new PMMB(codigo, titular, saldo, numMovs);
}
}
3.5 Mtodos e
variveis de classe
A definio de classe que foi apresentada neste captulo, e foi at utilizada em exemplos concretos, est
perfeitamente correcta, mas, no entanto, est incompleta. A razo muito simples. Como dissemos atrs,
quer as classes quer as instncias que so criadas a partir das classes tm uma coisa em comum: so
objectos.
As classes so objectos particulares dado que guardam a estrutura e o comportamento que vai ser comum a
todas as instncias a partir de si criadas. Porm, classes no deixam por isso de ser objectos.
Os objectos foram anteriormente definidos como sendo entidades que possuem uma estrutura de dados
privada e um conjunto de mtodos que representam o seu comportamento. Assim sendo, para que a definio
de classe esteja coerente com o facto de classes tambm serem objectos, ento uma classe dever poder ter a
sua prpria estrutura de dados e os seus prprios mtodos, para alm de possuir uma definio das variveis
e mtodos das suas instncias.
s variveis que representam a estrutura interna de uma dada classe designaremos por variveis de classe.
Aos mtodos que implementam o comportamento de uma classe designaremos por mtodos de classe. Os
mtodos de classe so activados atravs das mensagens correspondentes que devero ser enviadas classe.
Se uma classe possui variveis de classe, tal como para as instncias, o acesso a tais variveis dever apenas
ser realizado atravs de mtodos de classe de acesso a tais variveis, mantendo-se o princpio do
encapsulamento.
As variveis de classe so, em certas circunstncias, muito interessantes, dado que permitem guardar na
classe informaes que podem dizer respeito globalidade das instncias criadas e que no faria sentido
colocar em qualquer outro local, ou seja, variveis de classe so variveis acessveis classe e a todas as suas
instncias.
J JA AV VA A5 5 E E P PR RO OG GR RA AM MA A O O P PO OR R O OB BJ JE EC CT TO OS S ( (F F. . M M R RI IO O M MA AR RT TI IN NS S 2 20 00 06 6) )
28 Classes e Instncias
Por exemplo, imaginemos que no conjunto de requisitos para a definio de uma classe ContaBancaria
(no Banco, o que seria diferente) nos era solicitado o seguinte:
Dever ser possvel possuir a cada momento o nmero total de contas criadas;
Dever ser possvel possuir a cada momento o somatrio dos saldos das contas existentes.
Uma varivel que guarde o nmero total de contas j criadas no certamente uma varivel de instncia,
dado que nenhuma conta necessita de saber o total de contas j criadas. Admitindo, porm, que s
poderamos usar variveis de instncia para se guardar tal valor, que de mbito mais global do que o
mbito de uma instncia, dado que diz respeito a todas as instncias, ento, tal varivel de instncia, por
exemplo, totcontas, apareceria em todas as instncias de ContaBancaria e se, por exemplo, j
existissem 120 contas, em todas as instncias deveria aparecer com o valor 120, o que seria uma perfeita
redundncia. Pior ainda, logo que uma nova conta fosse criada, 120 mensagens deveriam ser de imediato
enviadas s 120 instncias, dando a indicao de que agora passaria a ser 121.
O mesmo raciocnio se aplica varivel que dever a cada momento conter o total dos saldos. Se um
depsito ou levantamento fosse feito numa conta, uma mensagem teria que ser enviada a todas as outras para
actualizar o saldo actual total: no teria sentido.
Por exemplo no caso da classe PMMB, poderamos necessitar de uma varivel que assegurasse que os
cdigos dos cartes emitidos fossem garantidamente sequenciais e que, portanto, nos obrigasse a saber a
cada momento quantas instncias de PMMB foram a cada momento j criadas, etc. No colocaramos tal
valor em cada carto, certamente.
Assim, as variveis de classe tornam-se muito teis para que nelas se possam guardar informaes que
dizem respeito classe e/ou a todas as suas instncias, tais como se exemplificou com os dois valores acima
introduzidos relativamente a ContaBancaria. Tais valores assumem um carcter de informao global
dentro do pequeno contexto classe e suas instncias, sendo acessveis e consultveis atravs dos mtodos de
classe, em funo dos modificadores de acessibilidade destes. As variveis de classe esto exclusivamente
associadas classe, tendo existncia real e podendo ser usadas mesmo se a classe no criou instncias.
As variveis de classe servem tambm, por vezes, para conter valores constantes, ou seja, imutveis a partir
da sua inicializao, funcionando pois como constantes de referncia, por exemplo, para clculos a realizar
pelas instncias da classe, clculos que desta forma so tornados rigorosos e, mais do que isso, normalizados,
dado serem garantidamente realizados por todas usando os mesmos valores. Por exemplo, se definirmos uma
classe Circulo com um mtodo de instncia area() e pretendermos que o valor de pi para o clculo da
rea seja sempre igual para todos os crculos criados, ento o melhor ser criarmos uma varivel de classe
que define o valor a ser usado por todos os crculos no clculo da rea, em vez de termos um valor de pi em
cada instncia, correndo-se o risco de serem diferentes.
Os mtodos de classe serviro, fundamentalmente, tal como os de instncia, para garantir o acesso e a
manipulao dos valores associados s variveis de classe. Aos mtodos de classe aplicam-se as mesmas
regras anteriormente definidas para os mtodos de instncia. Os mtodos de classe so sempre acessveis s
instncias da classe, porm, mtodos de classe no tm acesso a qualquer dos mtodos de instncia.
Quer os mtodos quer as variveis de classe distinguem-se dos de instncia pelo facto de que, nas suas
declaraes, imediatamente a seguir ao modificador de acesso, aparece declarado o modificador static,
que indica que, no contexto classe-instncias, existe apenas uma cpia destas entidades, residindo tal cpia
na classe.
Uma Classe passa assim a ser definitivamente definida como contendo:
A definio de um conjunto de variveis de classe;
A definio de um conjunto de mtodos de classe;
A definio de um conjunto de variveis de instncia;
A definio de um conjunto de mtodos de instncia.
A Figura 3.4 mostra a estrutura em geral usada para a especificao em abstracto de uma classe, ainda que a
mesma no seja completamente rgida. Por vezes, as variveis de instncia so definidas antes dos
C CC C C CC CL LL LL LL LA AA AA AA AS SS SS SS SS SS SS SS SE EE EE EE ES SS SS SS S E EE EE EE E I II I I II IN NN NN NN NS SS SS SS ST TT TT TT T N NN NN NN NC CC CC CC CI II II II IA AA AA AA AS SS SS SS S
Classes e Instncias 29
construtores dado estes lhes atribuirem valores iniciais e, ao codific-los, poder ser importante ter acesso
visual aos nomes das variveis.
CLASSE C
Variveis de Classe
Mtodos de Classe
Variveis de Instncia
Mtodos de Instncia

Figura 3. 4 Estrutura completa de definio de uma classe
Vamos em seguida apresentar a forma de declarao JAVA das variveis e dos mtodos de classe, voltando
ao exemplo concreto da classe PMMB, admitindo que pretendamos adicionalmente contar o nmero de
instncias criadas e o saldo total dos cartes.
Assim, imediatamente a seguir ao cabealho da declarao de classe, devemos declarar as variveis e
mtodos da classe que permitam realizar estes requisitos.
Vamos necessitar de duas variveis e dos respectivos mtodos de consulta e modificao das mesmas, pelo
menos. Ambas as declaraes so perfeitamente idnticas s declaraes j estudadas para os mtodos e
variveis de instncia, excepto num nico ponto: usam a palavra reservada static. Haver assim uma nica
cpia destas entidades que acessvel a todas as instncias da classe que forem criadas, o que corresponde
excatamente ao que pretendmos. Vejamos o novo cdigo da classe PMMB:
public class PMMB {
// Variveis de Classe
public static int numPMMB = 0;
public static double saldoTotal = 0.0;

// Mtodos de Classe
public static int getNumPMMB() {
return numPMMB;
}
public static double getSaldoTotal() {
return saldoTotal;
}
public static void incNumPMMB() {
numPMMB++;
}
public static void actSaldoTotal(double valor) {
saldoTotal += valor;
}
// Construtores
public PMMB() {
codigo = ""; titular = "";
saldo = 0.0; numMovs = 0;
this.actSaldoTotal(0);
this.incNumPMMB();
}
public PMMB(String codigo, String tit,
double sld, int nMovs) {
J JA AV VA A5 5 E E P PR RO OG GR RA AM MA A O O P PO OR R O OB BJ JE EC CT TO OS S ( (F F. . M M R RI IO O M MA AR RT TI IN NS S 2 20 00 06 6) )
30 Classes e Instncias
this.codigo = codigo; titular = tit;
saldo = sld; numMovs = nMovs;
this.actSaldoTotal(saldo);
this.incNumPMMB();
}
// Variveis de Instncia
private String codigo;
private String titular;
private double saldo;
private int numMovs; // total de movimentos
// Mtodos de Instncia
. . . .
public void carregaPM(double valor) {
saldo = saldo + valor;
numMovs++; actSaldoTotal(valor);
}
// pr-condio
public boolean prePaga(double valor) {
return saldo >= valor ;
}

public void pagamento(double valor) {
saldo = saldo valor;
numMovs++; actSaldoTotal(-valor);
}
public String paraString() { . . . }
. . . .
}
Note-se que mtodos de classe devem ter sempre como objecto receptor uma classe. Tal apenas opcional se
forem usados dentro da prpria classe. O acesso a variveis de classe pode ser feito tambm usando o
selector ponto (.), mas tambm aqui se aconselha o uso de mtodos de consulta, tal como para as instncias.
A sintaxe bvia a partir do momento em que definimos que uma classe tem um identificador iniciado por
uma letra maiscula e uma varivel por minscula.
Assim, frases como as seguintes no provocam qualquer tipo de dvida semntica.
pt1.incCoord(10, 5) // mtodo de instncia
Ponto.x // varivel de classe
ystem.out // varivel de classe
PMMB.incNumPMMB() // mtodo de classe
meuPMMB.getSaldo() // mtodo de instncia
Dos quatro mtodos de classe definidos, dois so simples interrogadores que do como resultado os valores
internos das variveis de classe, devendo portanto ser usados em expresses que tenham como receptor o
nome da classe, tais como:
int pMoedas = PMMB.getNumPMMB();
double saldos = PMMB.getSaldoTotal();
Outros so modificadores do estado das variveis de classe, sendo pois usados em expresses da forma
seguinte:
PMMB.incNumPMMB(); // ou apenas incNumPMMB();
PMMB.actSaldoTotal(valor);
Note-se ainda que, num construtor, a referncia this tanto pode estar associada a um mtodo de classe
como a um mtodo de instncia. Num mtodo de instncia tambm pode, mas por questes de clareza e
estilo no aconselhvel usar this associado a mtodos de classe (conforme em actSaldoTotal(-
valor);).
Sempre que pretendermos definir constantes de classe, isto , valores imutveis que so armazenados na
classe e utilizveis por qualquer instncia, ento, devemos adicionar o modificador final declarao da
C CC C C CC CL LL LL LL LA AA AA AA AS SS SS SS SS SS SS SS SE EE EE EE ES SS SS SS S E EE EE EE E I II I I II IN NN NN NN NS SS SS SS ST TT TT TT T N NN NN NN NC CC CC CC CI II II II IA AA AA AA AS SS SS SS S
Classes e Instncias 31
pseudovarivel, deste modo dando a indicao de que se trata de uma constante e, em geral, por uma
questo de estilo, usando apenas letras maisculas (e, por vezes, o _) no seu identificador, tal como em:
public static final double PI = 3.1415926535897932;
public static final int MAX_INT = 99999;
Possuindo tais identificadores valores por definio inalterveis, e dado possurem um estilo de declarao
diferente das classes, das variveis e dos mtodos, e ainda dado que o compilador de JAVA ao reconhec-los
como valores imutveis realiza a substituio imediata dos seus identificadores pelos respectivos valores, h
neste caso toda a vantagem em explicitamente se identificar tais constantes, da at a sua designao como
named constants.
Assim, sendo por definio imutveis, as constantes de classe podem ser usadas directamente sob a forma de
expresses via selector ponto (.) tal como em:
double area = Circulo.PI * Math.pow(raio, 2);
int x = ClasseX.MAX_INT * 10;
int minInt = Integer.MIN_VALUE; // constante da classe Integer
3.6 Importao
esttica
A partir de JAVA5, a linguagem passou a possuir tambm um mecanismo de importao esttica que
permite ao programador importar de uma dada classe um qualquer dos seus membros static, ou seja,
variveis ou mtodos de classe, e, a partir desse momento, poder us-los sem ter que usar como prefixo o
nome da sua classe. As instrues de import static devem ser escritas no incio dos ficheiros de
definio das classes, tal como as clusulas de importao at aqui estudadas.
Por exemplo, na classe Ponto, poderamos ento ter escrito:
import static java.lang.Math.*;
public class Ponto {
e, agora, ao longo do cdigo dos mtodos de instncia de Ponto, em vez de escrevermos Math.abs(x),
Math.pow(dx, 2), Math.sqrt(dy), Math.PI*5, bastaria escrever abs(x), pow(dx, 2), sqrt(dy) e
PI*5.
Se num programa principal escrevermos:
import static java.lang.System.out;
import static javax.swing.WindowConstants.*;
as nossas instrues de output podem passar a ter a forma mais simples:
out.println("xxxx");
setDefaultCloseOperation(EXIT_ON_CLOSE);
3.7 Classes no
instanciveis
A definio de uma classe na programao por objectos o processo central de concepo das entidades
computacionais que pretendemos construir. A classe permite que a partir dela sejam criadas tantas instncias
idnticas em estrutura e comportamento quantas as necessrias. Este , portanto, o desiderato fundamental da
criao e da utilizao de classes. As classes so tambm tipos pois as variveis so declaradas como sendo
referncias para objectos de dado tipo, ou seja, como sendo instncias de dada classe.
Porm, em algumas circunstncias especiais, pode fazer algum sentido a definio de classes que no vo
poder criar quaisquer instncias. Antes de nos debruarmos sobre a utilidade de tais classes, que no vo
J JA AV VA A5 5 E E P PR RO OG GR RA AM MA A O O P PO OR R O OB BJ JE EC CT TO OS S ( (F F. . M M R RI IO O M MA AR RT TI IN NS S 2 20 00 06 6) )
32 Classes e Instncias
poder criar quaisquer instncias, vejamos em que condies uma classe no pode criar as suas prprias
instncias.
Os componentes de uma classe que tm directamente a ver com a criao correcta de instncias dessa classe,
so no s os construtores mas tambm as variveis de instncia e os mtodos de instncia. Ora se uma dada
classe for definida como tendo apenas variveis e mtodos de classe, o que perfeitamente possvel em
JAVA, ento essa classe no especifica a estrutura e o comportamento de qualquer instncia, pelo que estas
no podero ser criadas, nem tal faria qualquer sentido.
Assim sendo, isto , no podendo tal classe criar instncias, qual o seu interesse ou vantagem num ambiente
de PPO? De facto, classes contendo apenas variveis e mtodos de classe podem ser auxiliares preciosos em
PPO, j que, mesmo que no permitam criar instncias suas, podem representar centros de servios, dado
disponibilizarem mtodos de classe que tm funcionalidades de grande utilidade, sem que haja necessidade
de criar instncias para que tal funcionalidade possa ser tornada acessvel.
Esta noo de uma classe como um centro de servios nico, sem instncias ou rplicas, pode ser ilustrada
recorrendo, por exemplo, classe de JAVA designada por Math, classe final que pertence ao package
java.lang, classe que coloca ao dispor dos seus clientes um conjunto de servios matemticos, como
sejam clculos trigonomtricos, converses entre graus e radianos, arredondamentos, clculo de logaritmos,
razes quadradas e quadrados, entre outros.
Todos estes servios so oferecidos por esta classe atravs de um conjunto de mtodos de classe de tipo
public static, invocveis portanto a partir de qualquer outra classe, e at importveis. Sendo mtodos de
classe, o utilizador de tais mtodos apenas ter que ter em considerao o facto de que as respectivas
mensagens devero ser enviadas a uma classe usando o seu identificador, excepto se for realizada a sua
importao esttica usando a instruo import static.
Esta possibilidade de concentrar um conjunto de servios numa nica classe no deve ser erradamente
confundida com o facto de que, em certas circunstncias, e em funo de certos requisitos de projecto, certas
classes surgem como devendo ter, no mximo, uma nica instncia (multiplicidade 1). Ter, no mximo, uma
instncia de uma dada classe nada tem a ver com a criao de uma classe para a qual no faz sentido criar
instncias, dado que a razo da sua existncia oferecer um conjunto de servios que no fazem sentido
ser replicados.
JAVA possui algumas classes deste tipo, de grande utilidade no desenvolvimento de aplicaes, sendo no
entanto pouco comum que, em projectos concretos, surja a necessidade de se desenvolverem classes com
estas caractersticas.
A classe Math que j anteriormente referimos , naturalmente, uma delas. Uma outra classe deste tipo a
classe Arrays que implementa um grande conjunto de mtodos (algoritmos) sobre arrays de tipos
primitivos, dado que os arrays, ainda que sendo de tipo referenciado, no so objectos e, portanto, no tm a
si associados quaisquer mtodos. Esta classe complementa-os no que diz respeito ao comportamento.
Outras classes deste tipo so as classes Beans, Arrays, Proxy, Collections, etc. A classe
Collections, por exemplo, complementa as coleces de objectos (que iremos estudar no captulo 8),
fornecendo mtodos de classe para ordenao de listas, para determinao do mximo elemento de uma
coleco, etc.
tambm comum que a classe de teste que se desenvolve para testar um dado conjunto de classes, possua
vrios mtodos de classe que so invocados a partir de main() e que ajudam a estruturar o cdigo,
facilitando a realizao de vrios testes. So mtodos de classe j que, como compreensvel, no h
qualquer objectivo em criar instncias desta classe de teste, mas apenas estrutrar o cdigo do mtodo
main().
Vejamos um exemplo de um programa em que lida uma sequncia de nmeros inteiros para um array e,
usando mtodos auxiliares de classe, determinamos o seu mximo e se faz a sua ordenao por ordem
crescente.
C CC C C CC CL LL LL LL LA AA AA AA AS SS SS SS SS SS SS SS SE EE EE EE ES SS SS SS S E EE EE EE E I II I I II IN NN NN NN NS SS SS SS ST TT TT TT T N NN NN NN NC CC CC CC CI II II II IA AA AA AA AS SS SS SS S
Classes e Instncias 33
import static java.lang.System.out;
import java.util.*;
public class ProgMainAuxs {
public static final int DIM = 100; // dimenso mxima
public static Scanner input = new Scanner(System.in);
// mtodo auxiliar para leitura do array
public static int[] leArray(int num) {
int[] nums = new int[num];
int n = 0;
for(int i = 0; i< num; i++) nums[i] = input.nextInt();
return nums;
}
// mtodo auxiliar que determina o mximo do array parmetro
public static int max(int[] nums, int total) {
int max = Integer.MIN_VALUE; // menor valor int
for(int i = 0; i<total; i++)
if (nums[i] > max) max = nums[i];
return max;
}
// O programa principal, desenvolvido no mtodo main()
// vai agora invocar os mtodos static auxiliares.
public static void main(String[] args) {
int[] arrayNum = new int[DIM];
out.print("Total de nmeros a ler: ");
int dim = input.nextInt();
arrayNum = leArray(dim);
int maximo = max(arrayNum, dim);
out.println("Mximo = " + maximo);
Arrays.sort(arrayNum);
out.println("Array Ordenado --");
for(int i = 0; i<dim; i++) out.println(arrayNum[i]);
int soma = 0;
for(int n : arrayNum) soma += n;
out.println("Somatrio = " + soma);
}
}
Neste programa usmos um mtodo auxiliar para leitura do array, outro para calcular o seu mximo e
usmos o mtodo sort(int[] a) da classe Arrays para ordenar o array de inteiros. Desta forma,
estruturmos melhor o cdigo do mtodo main(), que se torna mais simples e mais legvel. Criou-se uma
constante de classe DIM que define a dimenso mxima dos arrays a usar, e uma varivel input, que
global a todos os mtodos, e que se associa a uma instncia de Scanner para leitura de valores (via
System.in).
Estas classes so teis na medida em que prestam servios. Porm, deve ter-se em ateno que programar
usando mtodos e variveis de classe so excepes por utilidade. No programao por objectos, , de
facto, programao imperativa. Porm, os nossos programas principais, nos quais vamos criar instncias de
classes e realizar operaes com elas, tm sempre esta configurao, ou seja, so uma classe de alto nvel
onde se programa um mtodo main() e, eventualmente, alguns auxiliares, para criarmos os nossos objectos.
Neste exemplo, no foram objectos mas arrays, que so de tipo referenciado como se pode comprovar pela
instruo return nums; do mtodo leArray().
Outras classes no instanciveis mas essas no possuindo sequer cdigo, quer de mtodos de classe quer de
mtodos de instncia, sero estudadas posteriormente, classes que apesar de no conterem cdigo, sero de
grande utilidade, como veremos.
J JA AV VA A5 5 E E P PR RO OG GR RA AM MA A O O P PO OR R O OB BJ JE EC CT TO OS S ( (F F. . M M R RI IO O M MA AR RT TI IN NS S 2 20 00 06 6) )
34 Classes e Instncias
3.8 Classes Wrapper:
Integer, Double e
outras
No exemplo anterior, no clculo do mximo do array utilizou-se uma constante definida na classe Integer,
escrevendo Integer.MIN_VALUE, que corresponde ao menor valor inteiro possvel. As classes Integer,
Double, Float, Short, Long, Byte, etc., so classes de JAVA que foram desenvolvidas para
compatibilizar os tipos primitivos com o nvel dos objectos, sendo designadas por wrapper classes porque as
suas instncias so embrulhos, sob a forma de objectos, para valores de tipos primitivos.
As classes wrapper numricas criam objectos que guardam valores de tipo int, double, short, long,
float e byte, mas tais objectos tm a propriedade particular de serem imutveis, pois no existem mtodos
de instncia disponveis para modificar os seus valores. Para que os seus valores sejam alterados devero ser
convertidos num valor de tipo simples, modificados e depois convertidos de novo num outro objecto.
Cada uma destas classes possui duas constantes de classe que definem o maior e o menor valor de cada tipo
um dos tipos numrico primitivos (MAX_VALUE e MIN_VALUE). Cada uma destas classes possui tambm
diversos construtores e mtodos de classe para:
Converter valores de tipos primitivos em objectos (ex.: new Integer(int i), new
Double(double d), etc.);
Converter um objecto de uma das classes wrapper num valor de tipo numrico (ex.:
Integer.intValue(), Double.doubleValue(), etc.);
Converter um objecto de uma dada classe num valor de um tipo primitivo compatvel (ex.:
Integer.doubleValue(), Double.intValue(), etc.);
Criao de valores de um tipo numrico a partir da sua representao sob a forma de uma string (ex.:
int i = Integer.parseInt(String s));
Criao de um objecto a partir de uma string que representa o seu valor numrico (ex.: Double d =
Double.valueOf(String s)).
Estes mtodos encontram-se definidos em cada uma das classes wrapper, todos com a mesma semntica e
apenas variando o sufixo ou prefixo do seu identificador.
Vejamos alguns exemplos comuns de utilizao usando a classe Integer, exemplos que so extensveis a
todas as outras classes (substitudos os nomes de alguns mtodos):
Integer intg1 = new Integer(120); // int -> Integer
int val1 = intg1.intValue(); // Integer -> int
val1 = val1 + 2 ; intg1 = new Integer(val1);
String strVal = 123;
int val2 = Integer.parseInt(strVal); // String -> int
Integer intg2 = Integer.valueOf(strVal); // String -> Integer
double dbval = intg2.doubleValue(); // Integer -> double
int max = Integer.MIN_VALUE;
double maiorDouble = Double.MAX_VALUE;
Veremos em captulos posteriores outras formas de relacionamento entre classes, e mecanismos que traro
ainda maior modularidade e extensibilidade PPO em JAVA.