quarta-feira, agosto 30, 2006

Introdução à POO tendo c# como guia - parte 1

O objetivo deste artigo é ser uma introdução à Programação Orientada a Objetos (POO) primeiro a partir de um escopo global, depois sob a ótica do C#.

Se você já é programador, mas não conhecia ou utilizava POO em suas soluções, provavelmente sentirá uma enorme dificuldade em se adequar à POO, pois adotar POO é enxergar a programação sob um aspecto completamente diferente do usual. Apesar de difícil no início, POO traz enormes vantagens em termos de reusabilidade de código (você digitará menos e de forma mais eficiente =] ), melhoria na lógica da aplicação (ficará mais fácil “ver” como seu sistema funciona), manutenção (alterações nos programas serão menos traumáticas), colaboração (ficará mais fácil dividir o trabalho em equipe), etc. Você talvez esteja se perguntando; “Se POO integra todos esses benefícios, por que não é unanimidade entre os desenvolvedores?” Como dito no início, aprender POO não é fácil, mas o pior mesmo é alterar velhos hábitos cultuados por 50 anos de desenvolvimento de software baseado em programação estruturada.

CLASSES E OBJETOS

As linguagens orientadas a objeto, tem como idéia primordial tornar a estrutura e a lógica do programa um pouco mais próximos do mundo “real”. Basicamente temos em uma mesma unidade lógica funcional, que armazena em sua estrutura dados (equivalentes às variáveis) e meios de manipulá-los (equivalentes a procedimentos e funções). Estes dados são chamados de “campos de dados” e os meios de manipulação “campos de funções”. Tal unidade lógica é chamada de CLASSE. Recomendo que fixe bem este parágrafo antes de passar aos demais.

Uma classe é considerada um tipo de dado, como os tipos básicos pré-definidos (inteiro, real, string, etc.) em todas as linguagens de programação. O que quero dizer é que da mesma forma que podemos criar uma variável do tipo “boolean” também podemos criar uma variável do tipo da classe. Esta variável da classe é chamada de OBJETO.

Ao definirmos uma classe, estamos fornecendo o esqueleto para o objeto. Toda vez que declaramos uma variável originada de uma classe dizemos que ‘instanciamos um objeto”. Os campos de dados de uma classe após serem instanciados são chamados de “variáveis de instância” e os campos de funções de “métodos” ou “funções membros”. Então POO é isso? Definir tipos novos e usá-los? Na verdade a coisa é bem mais profunda. Quando definimos uma classe estamos criando um modelo – um molde – para criarmos objetos e/ou outras classes. Para que a POO esteja bem implementada os campos de dados não devem ser vistos e alterados de fora da classe diretamente. Quem deve manipular estes dados e “enxergá-los” são os campos de funções. Assim qundo este princípio da POO é seguido em uma classe, dizemos que os campos de dados estão “escondidos” ou seja, NÃO DEVEM SER ACESSADOS DIRETAMENTE DE FORA DE UMA CLASSE! Ok, mas porque devemos ter todo esse cuidado com os estes dados? Tal precaução existe para evitarmos alterações acidentais em dados que possam comprometer o bom funcionamento do programa. Assim ao declararmos um campo dentro de uma classe estamos escondendo-o do resto da aplicação. Também existe para evitarmos conflitos de nomes de variáveis, pois ambas não se enxergam. Isolar campos de dados e fazê-los ser acessíveis somente por campos de funções é uma técnica conhecida como encapsulamento. Encapsular sigifica esconder toda a complexidade do tratamento dos campos de dados, rotinas, etc. de fora de uma classe. Podemos “encapsular” tanto campos de dados quanto campos de funções. Quando os campos de dados estão encapsulados e escondidos fica fácil saber quando, como e onde um campo é acessado e alterado pois somente determinados campos de funções (métodos) podem acessá-los. Dentro dessa perspectiva existem campos de funções especiais, conhecidos como PROPRIEDADES. As propriedades de fora de uma classe são vistas como campos “descobertos”, mas de dentro da classe, são funções membros que permitem um meio seguro de acessar os campos de dados. As propriedades podem acessar campos de dados diretamente ou mesmo retornar valores calculados como se fossem campos de dados. Quando uma propriedade somente tem valor de retorno a mesma é dita como somente leitura. Quando chamamos uma função membro de um objeto, dizemos que estamos trocando mensagens com o objeto. De fato um programa em POO consiste em diversos objetos trocando mensagens entre si.

HERANÇA

Além de tudo POO possibilita a herança. Herança é uma forma de relacionarmos classes passando seus campos para outras de maneira hierárquica. Dessa forma se temos uma classe chamada “seres” com a característica “existir” ao relacionarmos esta como ponto chave da hierarquia com as classes “seres vivos”, “seres inanimados”, ambas herdaram da classe “seres” a característica “existir”. A classe que cede as características as demais é conhecida como “classe base” ou pai, e as que herdam “derivadas” ou filhas. A implementação de classes devem obedecer as características comuns a todo o sistema e então ir afunilando em características individuas de cada unidade do mesmo. Esta forma de progamação simplifica enormemente a manutenção do sistema, pois ao alterarmas uma característica em uma classe pai, automaticamente todas as filhas herdaram esta mudança. Ganhamos então um código altamente estruturado. Esta característica da POO é sem sombra de dúvidas um aliado fortíssimo das aplicações robustas e bem gerenciadas.

POFIMORFISMO E SOBRECARGA

Outra característica muito interessante e essencial se chama pofimorfismo, que é a capacidade campos de funções compartilhar o mesmo nome mas terem parâmetros, rotinas e saídas diferentes. Um caso particular de polimorfismo é chamado de sobrecarga. Sobrecarga ocorre por exemplo com o operado +, que serve para somas entre inteiros, reais, concatenação de strings, etc. O modo como o sistema processa cada uma das operações é completamente diferente.