POO-P-17-Associações-agregação | POO-P-19-Membros estáticos |
As linguagens de programação Java e C# possuem um conjunto especial de palavras reservadas cuja aplicação afeta como os membros de uma classe podem ser utilizados ou, até mesmo, como funcionam. São os especificadores e modificadores da linguagem.
Especificadores
Os especificadores existentes estabelecem a visibilidade do membro onde se aplicam, ou seja, determinam o seu acesso e, por isso, são conhecidos também como especificadores de acesso [2][4][5][6][7]. As linguagens de programação Java e C# possuem três especificadores de acesso: public, protected, private, visto no post sobre Encapsulamento.
public
Determina o acesso público, no qual os membros de uma classe têm utilização interna e externa irrestrita. Como ficam expostos na interface das classes, podem ser usados livremente pelas suas instâncias de maneira que os atributos públicos têm seus conteúdos acessados e alterados sem qualquer restrição; e os métodos públicos podem ser acionados arbitrariamente.
private
Estabelece o acesso privado, ou seja, define que o método ou atributo de classe assim declarado tem apenas uso interno, não sendo acessível externamente. Provê a ocultação dos membros assim declarados, servindo usualmente para compor a infraestrutura de uma classe.
protected
Indicar que membros de uma classe que não podem ser utilizados por meio de suas instâncias, mas apenas na construção de novas classes. Os membros protegidos, compõem uma interface de programação da classe, ou seja, um conjunto de atributos e operações destinados exclusivamente aos programadores que usarão tal classe como base para criação de outras.
Como visto no post sobre Encapsulamento, existe um quarto nível de acessibilidade denominado pacote (package) que não possui uma palavra reservada própria [4][7]. É o acesso padrão (implícito), quando outro especificador não é indicado. Seu efeito é tornar o membro público para as demais classes e instâncias presente no mesmo pacote, mas private para quaisquer outras.
O quadro que segue mostra o efeito da aplicação dos especificadores de acesso aos membros de uma classe, considerando as situações de implementação (codificação) e instanciação (criação de objetos dentro de programas).
Modificadores
Os modificadores determinam o funcionamento do membro, isto é, seu comportamento durante a execução dos programas, assim afetam como acontece a geração do seu respectivo código. Existem vários modificadores nas linguagens Java e C#: abstract, final, native, static, strictfp, synchronized, transient e volatile.
O quadro abaixo resume os efeitos provocados pelo uso destes modificadores, assim como sua aplicação típica.
O modificador static, cujo uso é bastante comum, será tratado no próximo post, que aborda os membros estáticos.
Os modificadores abstract e final serão abordados nos posts envolvendo herança e classes abstratas.
Os modificadores synchronized e volatile, destinados a programação com threads; transient, para uso junto a serialização; strictfp, para indicação de regras mais estritas para processamento de cálculos com uso de números em ponto flutuante; assim como native, empregado com o Java Native Inteface (JNI); são muito específicos e não serão abordados nesta série.
Particularidades do Java
A linguagem de programação Java, em particular, não possui os modificadores signed e unsigned existentes em outras, assim todos os seus tipos primitivos numéricos (byte, short, int, long, float e double) sempre podem representar valores positivos e negativos.
A notação ... (elipse) funciona como um modificador especial para tornar variável a lista de argumentos fornecida para um método (ou varargs) [7]. Seu uso permite que um método receba um número variável e arbitrário de valores, de maneira mais flexível que a recepção de arrays, pois seu uso admite o uso do método sem argumentos, com qualquer número de argumentos separados por vírgula (como uma lista) ou também um array.
O método que segue é do tipo varargs, ou seja, pode receber qualquer número de argumentos do tipo int, somando-os e retornando o resultado da soma.
public int somar(int ... args) {
int total = 0;
for (int i=0; i<args.length; i++) { total += args[i]; }
return total;
}
Observe que, internamente, os argumentos variáveis são tratados como se fizessem parte de um array, para o qual o número de elementos é indicado por length. Segue alguns exemplos de uso deste método.
int t1 = somar(); // uso válido, que retorna zero
int t2 = somar(0, 12, 34, 56);
int array[] = { 1, 2, 3, 4 };
int t3 = somar(array);
Finalmente, os métodos podem receber outros parâmetros, desde que aquele modificado com ... seja o último de sua assinatura.
Particularidades do C#
A linguagem de programação C# possui alguns modificadores próprios, como ref, out e param.
Por padrão a passagem de parâmetros em C# ocorre por valor, ou seja, uma cópia do valor ou do objeto indicado como argumento do método é passada como valor de seus parâmetros, de modo que se tal parâmetro é alterado dentro do método, nada ocorre com o valor original passado como argumento.
O modificador ref indica que o parâmetro será passado por referência, ou seja, o método receberá o endereço do valor ou objeto, de modo que sua alteração no interior do método acarreta mudanças no argumento usado para acionar o método, pois na verdade se trata da mesma variável ou objeto.
O modificador out, semelhante a ref, faz com que o parâmetro seja passado por referência, mas não necessita ser inicializado, ou seja, é geralmente utilizado para carregar valores para fora do método, possibilitando a existência de múltiplos valores de retorno. Por outro lado, parâmetros out devem ser inicializados dentro dos métodos onde são declarados.
Também existe modificador params, o qual permite que um método receba um número variável e arbitrário de valores, de maneira mais flexível que a recepção de arrays, pois seu uso admite o uso do método sem argumentos, com qualquer número de argumentos separados por vírgula (como uma lista) ou também um array.
O método que segue tem sua lista de parâmetros modificada com params, permitindo que receba qualquer número de argumentos do tipo int, somando-os e retornando o resultado da soma.
public int somar(params int args) {
int total = 0;
foreach (int v in args) { total += v; }
return total;
}
Observe que, como em Java, os argumentos variáveis são tratados como se fizessem parte de um array, possibilitando o uso de foreach. Segue alguns exemplos de uso deste método.
int t1 = somar(); // uso válido, que retorna zero
int t2 = somar(0, 12, 34, 56);
int array[] = { 1, 2, 3, 4 };
int t3 = somar(array);
Finalmente, os métodos podem receber outros parâmetros, desde que aquele modificado com params seja o último de sua assinatura.
Uso combinado de especificadores e modificadores
Os modificadores podem ser usados junto dos especificadores de acesso [7], por exemplo:
private static int MAX;
public static final double AVO = 6.22E23;
public static void main(String[] args) { ... }
protected transient boolean state;
public volatile long count;
private native byte AX;
public strictfp double computeSerie(double[] data) { ... }
public synchronized void turn() { ... }
public abstract Object[] toArray() { ... }
Desta forma, muitas possibilidades diferentes podem ser escolhidas pelo programador.
POO-P-17-Associações-agregação | POO-P-19-Membros estáticos |
Referências Bibliográficas
[1] JAMSA, K.; KLANDER, L.. Programando em C/C++: a bíblia. São Paulo: Makron Books, 1999.
[2] PAGE_JONES, M.. Fundamentos do Desenho Orientado a Objeto com UML. São Paulo: Makron Books, 2001.
[3] SOMMERVILLE, I.. Software Engineering. 6th. Ed. Harlow: Pearson, 2001.
[4] DEITEL, H.M.; DEITEL, P.J.. Java: como programar. 6a. Ed. São Paulo: Pearson Prentice-Hall, 2005.
[5] SAVITCH, W.. C++ Absoluto. São Paulo: Pearson Addison-Wesley, 2004.
[6] JANDL JR., P. Introdução ao C++. São Paulo: Futura, 2003.
[7] JANDL JR., P.. Java - guia do programador. 3a. ed. São Paulo: Novatec, 2015.
[8] RUMBAUGH, J.; BLAHA, M.; PREMERLANI, W.; EDDY, F.; LORENSEN, W.. Object-oriented modeling and design. Englewoods Cliffs: Prentice-Hall, 1991.
[9] STROUSTRUP, B.. The C++ Programming Language. 3rd Ed. Reading: Addison-Wesley, 1997.
[10] LANGSAM, Y.; AUGENSTEIN, M. J.; TENENBAUM, A. M.. Data structures using C and C++. 2nd Ed. Upper Saddle River: Prentice-Hall, 1996.
[11] WATSON, K.; NAGEL, C.; PEDERSEN, J.H.; REID, J.D.; SKINNER, M.; WHITE, E.. Beginning Microsoft Visual C# 2008. Indianapolis: Wiley Publishing, 2008.