Parte 1

<< Click to Display Table of Contents >>

Navigation:  Novatos > Orientação a objetos >

Parte 1

Previous pageReturn to chapter overviewNext page

Descrição

 

Este artigo tem como finalidade explanar a Programação Orientada a Objetos de uma maneira clara e superficial àqueles que ainda não a conhecem. Procura ilustrar apenas alguns dos principais conceitos da POO, mas de maneira prática e interessante, sem sobrecarregar os leitores, de modo que se possa preparar o terreno para outras explicações que envolvem a Orientação a Objetos venham em próximas publicações.

 

Pré-requisitos

 

Habilidade em programação com delphi em qualquer versão, conhecimento de Object Pascal e, principalmente, cabeça aberta.

 

O que é a Orientação a Objetos

 

Quantas vezes folheamos livros ou artigos de programação que falavam dessa tal “Programação Orientada a Objetos”, sem que entendêssemos sequer uma linha do que estava escrito? Muitas vezes. O que acontece é que esse par de letras “O” que tanto nos assusta, fica mais feio ainda depois de acompanhado de tantos palavrões, como “polimorfismo”, “herança múltipla”, “agregação” e outras greguices que insistem tanto em participar destes artigos.

 

Orientação a Objetos é o simpático nome que os pesquisadores da computação na década de 70 usaram para batizar este novo “paradigma”, que tinham acabado de inventar. E não é para menos, pois veremos que neste estilo de programação – como queriam os seus criadores – tudo é objeto. Ou ao mínimo, se pretende que seja.

 

Ainda como era nossa intenção falar, a Orientação a Objetos é um novo paradigma, que procura re-arranjar a programação estruturada de uma maneira diferente, e talvez bem mais compreensiva ao raciocínio do homem. Ela pretende descrever a solução através de objetos – como no mundo real – ao contrário da programação estruturada, que o faz através de passos e comandos, de maneira semelhante a uma receita de bolo.

 

Um paradigma, caso o leitor não saiba, é uma maneira diferente de se tentar enxergar uma mesma coisa, um mesmo mundo. O Paradigma OO busca bases filosóficas para tentar traduzir um mundo mais humano às instruções que o processador realmente entende. E é de viagens deste tipo, combinadas à estrutura de linguagens imperativas como o C ou Pascal, que surgem as linguagens OO. E estas últimas se responsabilizam pela existência da maioria dos grandes softwares produzidos nos dias atuais em todo o mundo.

 

Mas por que diabos isso foi inventado?

 

Desde que surgiu, a computação tem evoluído de uma maneira bastante rápida. Esta evolução acabou levando a comunidade deste meio a se deparar com a chamada “crise do software”. A orientação a objetos surgiu nos primórdios da década de 70, com as linguagens ADA, SIMULA e Small Talk. Ela ficou bastante difundida nos anos 80, com linguagens como o C++, e teve uma recente explosão em difusão nos anos 90, através da linguagem Java. Hoje em dia é muito comum encontrarmos compiladores e tradutores para linguagens OO, tais como Object Pascal, C++, Java e Visual Object.

 

A “crise do software” acabou levando os desenvolvedores da época a buscar uma solução alternativa, pois a complexidade dos sistemas já havia chegado a tal ponto que nem os seus programadores conseguiam dominá-la mais. Sabia-se que as linguagens estruturadas não davam mais suporte às necessidades, e esta possivelmente tenha sido a principal causa do surgimento das linguagens OO.

 

Também não é para menos. Se você tentar olhar um programa como o AutoCAD com os olhos de programador, irá entender o que queremos dizer com a palavra “complexidade”. Para um programador experiente em OO, fica difícil sequer imaginar uma solução destas sem que se modele um mundo de objetos. Daí a nossa intenção em dizer que a POO surgiu para suprir a crise do software – e conseguir dividir os sistemas de maior complexidade em partes independentes e que possam, assim, se manter sob o controle de seus criadores.

 

Afinal de contas, o que é um Objeto?

 

Os livros e artigos de OO costumam dizer que um objeto é qualquer coisa. Não que eles não tenham razão nesta frase, mas talvez não tenham muita clareza. Isto porque a resposta para essa pergunta deveria ser a mesma que você diria, se lhe perguntassem “O que é um objeto para você?”. Após responder a esta pergunta, basta tentar imaginar que você irá representar o mundo no seu programa, através de objetos, e o significado começa a brotar na cabeça. Um objeto, para você, o que é? Um lápis? Um tijolo? Um copo? Exatamente.

 

Por definição, um objeto pode ser entendido como alguma coisa que existe, que possui características, e que faz algo. Este conceito é ideal para explicarmos o que é um objeto dentro do programa, em termos da linguagem. Um objeto, numa linguagem OO, é um indivíduo que possui atributos (estado) e métodos (comportamento), tal qual o mesmo objeto visto no mundo real. Os atributos, conforme veremos, representarão dados e os métodos, trechos de código executável.

 

Se você já chegou até aqui, e mesmo assim não conseguiu entender completamente o que é objeto, não se preocupe. Provavelmente as coisas deverão clarear quando começarmos a ver isso na prática. E esta, conforme esperamos, deverá ser a melhor parte. Mas por enquanto, precisaremos apenas abordar mais algumas “coisinhas”, para que se possa colocar a mão na massa com um mínimo de confiança.

 

Classes e Instâncias

 

Para entender melhor os princípios da OO – por mais chato ou viajante que isto seja – é necessário abordar dois elementos essenciais: classe e instância. Estes elementos, que parecem estar mais ligados à filosofia do que à própria programação, são de fundamental compreensão aqui, mesmo com a mais simples das explicações. Portanto, caro leitor, nem pense em pular esta parte, ou então você será condenado a não entender praticamente nada mais à frente.

 

Podemos dizer que classes são o conjunto de todos os elementos semelhantes, no nosso caso, objetos. Todo objeto pertence a uma determinada classe, assim na terra como no céu, isto é, assim no mundo real quando no “mundo” descrito no programa. Classes são tipos de coisas, e descrevem as coisas de uma maneira generalista, através de regras a que todos os elementos que a ela pertencem devem seguir, sem que necessariamente se conheça uma ou outra dessas “coisas”.

 

Assim existe, por exemplo, a classe dos livros, a que pertencem todos os livros publicados. À classe dos equipamentos eletrônicos pertencem todos os computadores, televisores e outros dispositivos, bem como à classe dos humanos se espera que pertençam todas as pessoas.

 

Em contrapartida, citamos a instância, que significa um elemento específico daquela classe. Uma instância é um constituinte singular e conhecido da população daquela classe. A instância, ao contrário da classe, procura referir um elemento conhecido da sua classe.

 

Assim como você é uma instância da classe dos humanos, tal qual este monitor à sua frente é uma instância da classe de equipamentos eletrônicos, ou ainda aquele livro de Biologia de Soares disposto ao lado de sua cabeceira é uma instância da classe dos livros. Instâncias são, portanto, casos de ocorrência das classes.

 

Agora tratando novamente de classes, porém em termos de programação, diremos que elas são tipos declaráveis. No Delphi, a declaração de uma classe, é feita através da palavra reservada class, como segue abaixo:

 

unit Unit1;

 

 

type

 

  TAnimal = class

  end;

 

Logo, TAnimal representará a classe dos animais, e nela serão definidas as características (regras) a que todo e qualquer animal deverá seguir. Vale lembrar que, por padrão no Delphi, convenciona-se os tipos como identificadores começados com a letra T.

 

Entretanto, embora tenhamos acabado de criar a classe dos animais, ainda não existe nenhum animal no nosso sistema. Isto porque não existe nenhuma referência a um animal, muito embora o compilador já “saiba” da possível existência dos animais. Para que possamos referenciar uma instância de animal, declararemos uma variável do tipo TAnimal:

 

var

  MeuAnimal: TAnimal;

 

Isto, teoricamente, resolve o nosso problema. Até porque agora já temos uma referência a um animal, apesar de não o conhecermos. Mais adiante veremos que isso não é exatamente verdade, mas vamos considerar que ele existe, por enquanto. Agora você sabe que possui um animal, e que se referiu a ele como MeuAnimal.

 

Atributos

 

Bom, você já declarou sua primeira classe. Mas o que ela faz? Para que ela serve? Absolutamente nada, por enquanto. Como sugerimos antes, um objeto é uma entidade que deve possuir estado e comportamento. E é para dar esta vida aos objetos que lhes caracterizamos com atributos e métodos. E nesta seção vamos explicar como dar estado ao objeto, ou seja, dar-lhe a capacidade de guardar informações.

 

Voltando ao nosso primeiro exemplo, iremos aperfeiçoar melhor a descrição do nosso animal, dando-lhe duas características, altura e peso. Também vamos personalizá-lo, dando-lhe a possibilidade de ter um nome. O nosso exemplo ficará assim:

 

unit Unit1;

 

 

type

  TAnimal = class

    Nome: string;

    Altura, Peso: real;

  end;

 

Bom, a partir de agora o seu objeto já possui a capacidade de guardar informações dentro dele. Poderíamos dar um nome, uma altura e um peso a MeuAnimal, acessando os seus dados internos (atributos) como no exemplo abaixo:

 

implementation

 

procedure TForm1.Button1Click(Sender: TObject);

begin

  MeuAnimal.Nome := 'Cachorro Plutão';

  MeuAnimal.Altura := 0.72;

  MeuAnimal.Peso := 9.3;

end;

 

Entretanto, se você compilar o seu projeto, e mandar que ele execute este código, ele não deverá funcionar, levantando um erro de violação de acesso. Mas porque? Simples e óbvio. Você realmente ordenou ao sistema que ele atribuísse o nome, peso e a altura ao MeuAnimal, mas você esqueceu de dizer quem era ele. Em outras palavras, a sua referência MeuAnimal está apontando para ninguém. Em termos do Delphi, digamos que ela é nula, ou seja, possui valor nil.

 

Mas então para quem eu devo fazê-la apontar? Eis a questão. Acontece que não existe nenhum animal no seu sistema. Se você voltar alguns parágrafos deste texto, onde ainda falávamos do que vem a ser um objeto, se lembrará que um fundamento básico e filosófico do objeto é existir. E para que alguma coisa passe a existir, ela primeiro deve ser criada. E assim como no mundo real, através de chamadas específicas, faremos objetos serem construídos e destruídos.

 

Construtores e Destruidores

 

Construtores e destruidores são métodos especiais – mais abaixo explicaremos melhor o que são métodos – responsáveis pela criação e destruição de objetos. Os especialistas em linguagens orientadas a objeto costumam dizer que eles são métodos de classe. Mas isso não vem muito ao caso aqui.

 

O que importa é que em algum momento do nosso exemplo, um animal precisa ser criado, até para que possa receber aqueles valores que tentamos lhe atribuir mais acima. E é justamente esse o papel que tem um construtor. O construtor de uma determinada classe seria um método ou procedimento capaz de criar, ou instanciar, um objeto pertencente àquela classe. Sendo assim, para que construamos o nosso animal, usaremos a seguinte linha de código:

 

MeuAnimal := TAnimal.Create;

 

Esta chamada irá invocar o construtor padrão da classe, derivado da classe ancestral de todas, a classe TObject. Mas não se preocupe com isso agora. O importante é que, a partir da execução desta linha de código, passa a existir uma instância de TAnimal no seu programa, com memória alocada para ela, e MeuAnimal agora aponta para esta instância. Tão logo, para que aquele nosso código que resultou em erro funcione, vamos refazê-la da seguinte maneira:

 

procedure TForm1.Button1Click(Sender: TObject);

begin

  MeuAnimal := TAnimal.Create;

  MeuAnimal.Nome := 'Cachorro Plutão';

  MeuAnimal.Altura := 0.72;

  MeuAnimal.Peso := 9.3;

end;

 

Uma vez feito isto, e depois de executado este bloco de código, MeuAnimal passa a existir na memória, e a armazenará os dados que ora inserimos nele. Se não acreditar, ou se quiser ter certeza disto, execute o bloco de código seguinte:

 

procedure TForm1.Button2Click(Sender: TObject);

begin

  ShowMessage('Meu nome é ' + MeuAnimal.Nome);

  ShowMessage('Minha altura é ' + FloatToStr(MeuAnimal.Altura) + ' cm');

  ShowMessage('Meu peso é ' + FloatToStr(MeuAnimal.Peso) + ' kg');

end;

 

Agora que já sabemos o que é um construtor, passemos para o destruidor (ou destrutor, no vício da tradução). Um destruidor, como sugerido antes, é capaz de destruir o objeto em questão, liberando a memória que foi alocada para ele. MeuAnimal, portanto, deixa de existir a partir do momento que executamos esta linha de código:

 

procedure TForm1.Button3Click(Sender: TObject);

begin

  MeuAnimal.Destroy;

end;

 

A área de memória reservada para aquele TAnimal foi liberada. Entretanto, é importante ressaltar que isto não limpa a referência MeuAnimal, que continua apontando para a região de memória onde estava o TAnimal. Esta inconsistência pode trazer conseqüências desagradáveis para o sistema. Portanto, para um código seguro, sempre informe às referências que elas não mais apontam para ninguém, imediatamente após destruir os objetos:

 

procedure TForm1.Button3Click(Sender: TObject);

begin

  MeuAnimal.Destroy;

  MeuAnimal := nil;

end;

 

Métodos

 

Conforme dissemos já algumas vezes, um método é um bloco de código executável, capaz de definir comportamento ao objeto. Ao grosso modo, um método pode ser entendido como um procedimento (procedure) ou função (function), porém com a diferença de que ele se limita – ou ao menos deve se limitar – ao escopo do objeto a qual ele pertence. Métodos, de uma maneira geral, estão vinculados às instâncias.

 

Não fugindo muito da prática, e como se era de esperar, voltemos ao nosso velho exemplo do animal. Já lhe demos a capacidade de possuir estado, guardando algumas informações. Agora lhe daremos a possibilidade de se comportar, ou seja, literalmente o animaremos. Acrescentaremos em TAnimal três métodos: Correr, Crescer e Encolher. Estes métodos lhe darão a possibilidade de mudar seu estado. Vejamos como fica a nossa declaração:

 

unit Unit1;

 

type

  TAnimal = class

    Nome: string;

    Altura, Peso: real;

  procedure Correr;

  procedure Crescer(const incremento: real);

  procedure Encolher(const decremento: real);

end;

 

var

  MeuAnimal: TAnimal;

 

implementation

 

procedure TAnimal.Crescer(const incremento: real);

begin

  Altura := Altura + incremento;

  ShowMessage('Minha nova altura é ' + Altura);

end;

 

procedure TAnimal.Encolher(const decremento: real);

begin

  Altura := Altura - incremento;

  ShowMessage('Minha nova altura é ' + Altura);

end;

 

procedure TAnimal.Correr;

var 

  i: Integer;

begin

  ShowMessage('Eu, ' + Nome + ', estou correndo!');

  for i := 1 to 5 do

  begin

    ShowMessage('Estou no meu passo de número ' + IntToStr(i));

  end;

  ShowMessage('Eu, ' + Nome + ', cansei de correr.');

end;

 

E invocaremos os métodos conforme abaixo:

 

procedure TForm1.Button4Click(Sender: TObject);

Begin

  MeuAnimal.Crescer(0.1);

  MeuAnimal.Encolher(0.5);

  MeuAnimal.Crescer(0.3);

  MeuAnimal.Encolher(0.2);

end;

 

procedure TForm1.Button5Click(Sender: TObject);

begin

  MeuAnimal.Correr;

end;

 

Se o leitor pôde perceber, os métodos da classe TAnimal manipulam diretamente os atributos, fazendo com que o objeto dono do método invocado – ele e somente ele – seja manipulado. E é exatamente essa a proposta de definição de comportamento dos objetos, manipular dados dentro de seu escopo.

 

Muitos outros métodos são e devem ser desenvolvidos, de maneira a descrever, da maneira mais adequada possível, o comportamento desejado do objeto diante do sistema. Entretanto, veremos mais adiante, numa próxima publicação, onde abordaremos outros conceitos da OO.

 

Considerações Finais

 

Este artigo, como há de se perceber, está longe de estar completo. Muitos dos conceitos fundamentais da OO não foram tratados aqui, e o projeto, tal qual o desenvolvimento de sistemas orientados a objeto, requerem mais conceitos que não couberam aqui. Pretendemos que mais três partes deste mesmo texto sejam publicadas, de maneira contínua. Esta é apenas a primeira, e a mais introdutória delas.

 

O artigo não pretendeu, de maneira nenhuma, ser fonte bibliográfica sobre orientação a objetos. O seu objetivo foi, acima de tudo, trazer à luz da realidade os conceitos da OO, esta que sofre uma certa resistência por parte dos programadores, principalmente dos menos experientes, acabando por ser isolada, graças ao preconceito.

 

Outras abordagens estarão disponíveis nos nossos próximos artigos, de modo que possamos dar uma visão geral e clara sobre outros conceitos importantes da OO. Procuraremos, na medida do possível, e de maneira semelhante, trazer práticas do que for mostrado. Tentaremos desmistificar a OO, para que cada vez mais possamos perder o medo deste paradigma de programação que, quando bem usado, pode fazer coisas fantásticas.

Mais

Parte 2