• Nenhum resultado encontrado

16 Classes e objectos

No documento Programacao Em Java (páginas 37-44)

A programação orientada aos objectos refere-se à construção de programas que funcionam essencialmente à custa de elementos (objectos) que possuem características próprias e que são capazes de desempenhar tarefas. É através destas funcionalidades e dos mecanismos de inteiração entre os objectos que os programas trabalham.

Em Java, como em qualquer linguagem orientada a objectos, não é possível definir objectos sem definir primeiro a classe a que pertencem. Uma classe é usada para criar um ou mais objectos, definindo os seus atributos e comportamentos. Assim a definição de uma classe implica a especificação dos atributos (variáveis) e dos comportamentos (métodos) que os objectos criados a partir dela devem possuir.

Um objecto pode ser caracterizado por três componentes: Identidade

Atributo

Comportamento.

Deste modo é comum ter num programa objectos semelhantes, com mesmo comportamento, mas com atributos e identidade diferentes.

Um objecto é assim definido como uma instância de uma classe e possui todas as variáveis (atributos) e métodos (comportamentos) definidos por essa classe. Uma vantagem da programação orientada aos objectos é, então, permitir reunir na forma mais simples os seus atributos e comportamento, o que permite modelar de forma mais simples e aproximada os elementos do mundo real.

16.1 Criação de uma Classe 

A criação de uma classe passa pela definição dos atributos e dos comportamentos que os objectos criados a partir dessa classe devem apresentar.

Exemplo:

public class Motor //nome da classe {

//Área reservada ao código }

16.1.1 Atributos

Entre vários atributos destacamos velocidade, número do motor. A sua declaração pode

se feita da seguinte forma:

public class Motor //nome da classe {

//Área reservada ao código //Atributos da classe

private int velocidade private String numMotor }

De notar a utilização da palavra reservada private, em vez de public, na declaração dos

atributos. Desta forma, indica-se ao compilador que estas variáveis só podem ser acedidas directamente pelos métodos (comportamentos) definidos na própria classe. Assim, os atributos de um objecto criado a partir da classe mantêm-se inacessíveis a partir de qualquer outro objecto, ainda que criado a partir da mesma classe. Esta opção permite criar cada objecto como uma entidade fechada ou encapsulada, cujos detalhes internos não são visíveis a partir do exterior e cuja utilização é independente do contexto em que a mesma se faça.

16.1.2 Construtores

Cada classe dever ter pelo menos um construtor. Trata-se de um tipo especial de método utilizado apenas na criação e inicialização de objectos da classe. Distinguem-se dos restantes métodos por terem o mesmo nome da classe e por não terem valor de retorno, nem mesmo void.

Os construtores não são chamados como os outros métodos. Apenas a instrução de criação de objectos da classe os pode chamar (como será descrito na secção 1.2). Estes métodos são usados muitas vezes para inicializar os atributos de um objecto. No caso da classe Motor, o construtor pode ser:

public Motor(int velocidade, String numMotor) //nome do construtor {

//Inicialização dos atributos this.velocidade = velocidade; this.numMotor = numMotor; }

16.1.3 Métodos

Para além do construtor, podem ser considerado o seguinte comportamento para a classe motor:

public alteraVelocidade(int velocidade) //nome do método {

//mudança da velocidade

this.velocidade = velocidade; }

16.2 Criação de objectos 

A declaração de um objecto pode ser feita com uma declaração semelhante à das variáveis de tipos primitivos:

//Declaração de um objecto de nome nomeDoObjecto //pertencente a classe ClasseDoObjecto

ClasseDoObjecto nomeDoObjecto;

Concretizando o caso do Motor: Motor motor;

É importante realçar que esta declaração por si só não cria o objecto. Apenas cria na memória um espaço capaz de armazenar um endereço do espaço de memória onde um objecto desse tipo deste tipo venha a ser armazenado. A este espaço de memória chama- se referência, por permitir referenciar um objecto quando ele for criado. Nesta altura

sabe-se que motor pode vir a referenciar um objecto da classe Motor, mas o seu valor, neste momento, é indefinido.

A criação de objectos é realizada através do operador new. Este operador deve ser

seguido do nome da classe a partir da qual se pretende criar o objecto e de parêntesis (), eventualmente contendo um conjunto de parâmetros. Genericamente, a criação de um objecto tem a seguinte sintaxe:

//Declaração de um objecto de nome nomeDoObjecto //Pertencente a classe ClasseDoObjecto

ClasseDoObjecto nomeDoObjecto = new ClasseDoObjecto(parâmetros);

O operador new encarrega-se de chamar o construtor da classe, permitindo a realização

das operações de inicialização nele definidas. De facto, o que aparece à frente de new é a

instrução de chamada do método construtor da classe, incluindo também os respectivos parâmetros, se houver. Concretizando para o caso da classe Motor, instrução seguinte

permite criar um novo objecto da classe Motor, guardar o seu endereço na referência

motor e inicializar os seus atributos:

O operador new reservou um espaço de memória suficiente para armazenar todos os

atributos (variáveis) do objecto, bem como para guardar uma cópia em bytecode de

todos os métodos na classe Motor. O endereço de memória a partir do qual o objecto foi

armazenado foi armazenado (0x40506070 neste exemplo) é guardado na referência motor, permitindo o acesso posterior ao objecto à sua custa. A localização de um objecto

em memória não é controlada pelo programador, ficando o espaço respectivo ocupado até que o objecto seja destruído.

Tendo em conta que uma referência não tem utilidade antes de ser colocada a apontar (referenciar) para um objecto, é comum juntar as instruções de criação da referência e do objecto numa só.

Motor motor = new Motor(40,1232004F);

O objecto assim definido é um representante da classe, caracterizado pelo seu conjunto de dados. Em terminologia de programação orientada aos objectos, diz-se que o objecto é uma instância da classe, pelo que as suas variáveis (atributos) são variáveis da instância. O processo de criação de objecto chama-se instanciação.

A alteração do valor de uma variável deve ser feita com cuidado, pois pode levar à perda de objectos por ela referenciados. Para concretizar esta questão, vamos supor que foram criadas duas referências, motor1 e motor2, para objectos da Classe Motor. Suponhamos

0x40506070 motor 0x40506070 40 Motor() // Bytecode alteraVelocidade() // Bytecode 1232004F

também que foram criados dois objectos, cada um deles referenciado por uma das referências.

Motor motor1 = new Motor(10,4562004Z); Motor motor2 = new Motor(50,7682004B);

Este conjunto de instruções dá origem à situação descrita na figura seguinte:

Existem dois objectos em sítios diferentes da memória, cada um deles acessível por uma referência. A instrução seguinte é válida do ponto de vista sintáctico.

motor1=motor2; 0x40106070 motor1 0x40106070 10 Motor() // Bytecode alteraVelocidade() // Bytecode 4562004Z 0x40101010 motor1 0x40101010 50 Motor() // Bytecode alteraVelocidade() // Bytecode 7682004B

Um erro comum é utilizar esta instrução com o objectivo de atribuir ao primeiro objecto os dados do segundo. De facto, esta instrução não iguais os objectos, mas as referências, atribuindo o valor da segunda à primeira. O resultado é o da figura seguinte:

O que aconteceu foi na realidade foi a atribuição À variável motor1 do conteúdo de motor2 (0x40101010), fazendo com que ambas fiquem a referenciar o mesmo objecto.

Esta situação dever se encarada com algum cuidado, pois, por vezes, há a tendência para pensar que se há duas referências diferentes, então também há dois objectos diferentes, o que nem sempre é verdade, como se mostra no exemplo anterior.

O primeiro objecto está agora inacessível, pelo que ocupa espaço de memória inutilmente. O intérprete de Java efectua periodicamente a libertação de memória por objectos sem referência válida, devolvendo ao sistema operativo, de modos a que possa voltara ser utilizado. Este processo é conhecido na terminologia inglesa como garbage collection(recolha de lixo).

Dois aspectos devem ser destacados em relação a esta classe Motor. 0x40106070 Motor1 0x40106070 10 Motor() // Bytecode alteraVelocidade() // Bytecode 4562004Z 0x40101010 Motor1 0x40101010 50 Motor() // Bytecode alteraVelocidade() // Bytecode 7682004B

Primeiro é que, do ponto de vista de programa o funcionamento interno da classe Motor é

irrelevante e não necessita de ser conhecido. Basta saber, por exemplo, que o método

alteraVelocidade() alterva a velociade do motor, não sendo necessário saber como se

faz.

O segundo aspecto que deve ser realçado é a forma como os métodos são chamados ou, em terminologia orientada aos objectos, como se envia uma mensagem a um objecto. Uma mensagem é um pedido que se faz a um objecto para que apresente um comportamento. Claro que o objecto terá que ser uma instância de uma classe em que esse comportamento esteja definido. Para enviar uma mensagem a um objecto é necessária uma instrução que contenha:

Uma referencia ao objecto receptor (por exemplo motor1);

Um ponto

A mensagem que se pretende enviar (por exemplo altervaVelocidade()).

Assim se justifica, por exemplo, a instrução:

Motor1.alteraVelocidade(100);

16.3 Cópia de objectos 

Quando se fala de cópia de objectos os principiantes da programação orientada a objectos podem perceber que para o efeito é necessário fazer o seguinte:

x=y;// sendo x e y objectos.

Ora, a instrução anterior significa que x passa apontar ondeyaponta, graficamente seria:

Então para copiar um objecto a instrução de atribuição de atribuição não serve. Para criar realmente uma cópia de um objecto que tenha espaço na memória pode-se usar o método

clone(). A sintaxe é a seguinte:

novoObjecto = umObjecto.clone() y

No documento Programacao Em Java (páginas 37-44)

Documentos relacionados