Você está na página 1de 11

3 - Conceitos de Orientao aos Objectos

Hoje em dia, praticamente todo o software est a ser escrito numa ou noutra linguagem orientada aos objectos. As linguagens estruturadas como o C e o Pascal tiveram muito sucesso nos anos 70 e 80. Desde os anos 90 que a programao orientada aos objectos OOP (Object-Oriented Programming) ganhou especial relevncia, dominando a indstria informtica. Os exemplos mais familiares de linguagens orientadas aos objectos so o C++, o Java, o Delphi e o SmallTalk. Porqu esta mudana? As linguagens estruturadas tm um modelo de programao simples. Tipicamente, o programador pensa numa ou mais estruturas de dados que lhe modele o problema e, em seguida, desenvolve um conjunto de operaes (funes) que actuam sobre essas estruturas de dados (figura 3.1).

Figura 3.1 Modelo da programao estruturada

Embora este modelo de desenvolvimento funcione bem para pequenos programas, existem srios problemas quando a dimenso dos sistemas comea a aumentar.
FCA - Editora de Informtica

45

C# 2.0

O problema que uma vez que todas as operaes tm acesso a todos os dados, uma pequena modificao num dos mdulos pode ter implicaes em todo o programa. medida que os programas crescem, torna-se muito difcil manter o cdigo. simples de constatar: mudar o nome de uma varivel numa estrutura de dados pode implicar mudar o seu nome em milhares de linhas de cdigo onde esta utilizada. Vejamos um outro exemplo: se uma funo pode alterar o valor de uma varivel global, sem que o resto das funes tenham conscincia ou esperem essa alterao, isso poder levar a graves erros de funcionamento. Estes problemas so muito difceis de retirar do cdigo. Costuma-se dizer que neste tipo de arquitectura existe um elevado acoplamento entre mdulos. A programao orientada aos objectos tenta aliviar alguns destes problemas. A ideia principal diminuir o acoplamento entre os diversos mdulos. Para isso, cada uma das estruturas de dados encapsulada dentro de um objecto, que tambm possui funes que actuam sobre essa estrutura de dados. Os dados no so directamente visveis para o exterior do objecto. Apenas a interface, isto , as operaes disponibilizadas no objecto, visvel. Em OOP o programador pensa em termos de objectos que modelam o seu problema e nas relaes entre eles. As estruturas de dados especficas e a implementao das operaes sobre as mesmas devem ser apenas detalhes de implementao. A figura 3.2 ilustra esta ideia.

Figura 3.2 Modelo da programao orientada aos objectos

Uma questo bastante complexa a forma como se consegue chegar a um conjunto de objectos e relaes que modelem o problema correctamente. O objectivo deste livro no ensinar o leitor todo este processo. O tema demasiado extenso e complexo para o discutirmos em profundidade aqui. Caso o leitor no tenha experincia em design orientado ao objecto, recomendamos o livro de Grady Booch Object-Oriented Analysis and Design with Applications. No realmente possvel aprender a programar bem no paradigma de orientao aos objectos, lendo simplesmente um livro que ensina a sintaxe usada numa linguagem. Embora isso seja mais ou menos possvel numa linguagem estruturada, os conceitos envolvidos em orientao aos objectos so muito mais elaborados. usual dizer-se que para aprender OOP comea-se por ler um livro que
46
FCA - Editora de Informtica

CONCEITOS DE ORIENTAO AOS OBJECTOS

ensine a sintaxe de uma linguagem OOP, em seguida l-se um livro sobre design OOP e finalmente, s a experincia pode ajudar o programador. No entanto, antes de comearmos a discutir a sintaxe do C# em detalhe, vamos discutir um pouco dos principais conceitos associados OOP.

3.1 Conceitos bsicos


A programao orientada aos objectos assenta em trs conceitos bsicos fundamentais: encapsulamento de informao, composio/herana e polimorfismo. Iremos examinar cada um deles. No entanto, caso o leitor no consiga perceber todos os conceitos, no se preocupe. Mais frente iremos discutir em detalhe a sintaxe utilizada. Nesta altura o que importa ficar com as noes bsicas sobre estes trs pilares fundamentais. Todos os conceitos aqui abordados sero largamente examinados em captulos posteriores.

3.2 Encapsulamento de informao


Tal como foi dito antes, um dos pontos fulcrais da OOP o esconder as estruturas de dados dentro de certas entidades (objectos), aos quais so associadas funes (mtodos) que manipulam essas estruturas de dados. As estruturas de dados no devem ser visveis para outros objectos, apenas a sua interface (isto , os seus mtodos ou funes). Como que se comea este processo? O programador comea por definir classes. Uma classe representa um tipo abstracto de dados famlias de entidades. Por exemplo, um empregado de uma empresa poder corresponder a uma classe Empregado:
class Empregado { private string private int Nome; Idade; // Nome da pessoa // Idade da pessoa

// Construtor: inicializa os elementos internos de um objecto public Empregado(string nomeDaPessoa, int idadeDaPessoa) { Nome = nomeDaPessoa; Idade = idadeDaPessoa; } // Mostra a informao sobre a pessoa public void MostraInformacao() { Console.WriteLine("{0} tem {1} anos", Nome, Idade); }

Um Empregado tem internamente armazenado um nome e uma idade. de notar que antes da declarao das variveis Nome e Idade encontra-se a palavra-chave private. O que isto quer dizer que apenas esta classe pode utilizar estas variveis. Nenhuma outra classe pode aceder s variveis. A informao escondida dentro da sua classe.
FCA - Editora de Informtica

47

C# 2.0

Esta classe possui tambm um construtor Empregado(string nomeDaPessoa, int idadeDaPessoa) e um mtodo MostraInformacao(). Ambos so public. Sempre que uma entidade declarada como public, qualquer outra lhe pode aceder. Sempre que uma entidade declarada como private, apenas os elementos pertencentes mesma classe lhe tm acesso. Para que serve o construtor? O construtor permite criar uma nova instncia da classe. Isto , permite criar um novo objecto dessa classe. Por exemplo:
Empregado chefeProjecto = new Empregado("Lus Silva", 34); chefeProjecto.MostraInformacao();

faz com que seja criada uma nova instncia da classe (um objecto), que ir guardar o nome e a idade do empregado no seu interior. Ao chamar chefeProjecto.MostraInformao(), o mtodo invocado naquele objecto em particular o empregado Lus Silva. Em qualquer altura podemos criar diversos objectos da mesma classe, que estes possuem identidades distintas:
Empregado engenheiro1 = new Empregado("Magda Dionsio", 25); Empregado engenheiro2 = new Empregado("Ceclia Cardoso", 25); engenheiro1.MostraInformacao(); engenheiro2.MostraInformacao();

Ao executar este segmento de cdigo, surgir no ecr:


Magda Dionsio tem 25 anos Ceclia Cardoso tem 25 anos

de notar que no vlido escrever expresses como:


Console.WriteLine("{0}", engenheiro1.Nome);

Uma vez que Nome declarado como private, apenas elementos da sua prpria classe lhe conseguiro aceder. certo que possvel declarar todos os elementos de uma classe como sendo pblicos, mas a esto a perder-se todas as vantagens de utilizar uma linguagem orientada aos objectos, pois est-se a aumentar o acoplamento total da aplicao. Uma outra questo importante o operador new. Este operador utilizado sempre que se est a criar uma instncia de uma classe, isto , um objecto. Este operador trata de encontrar e reservar a memria necessria para conter o objecto e de chamar o construtor do mesmo, finalmente retornando uma referncia para o objecto criado.

3.3 Composio e herana


Quando um programador est a desenhar uma aplicao orientada aos objectos, comea por tentar encontrar classes. Cada classe tem uma determinada responsabilidade e representa uma entidade concreta do mundo real. Uma classe pode ter no seu interior objectos de outras classes ou relaes para estes. Por exemplo, podemos ter na classe Empregado um objecto do tipo Casa e um objecto do tipo Telemovel (figura 3.3). Por sua
48
FCA - Editora de Informtica

CONCEITOS DE ORIENTAO AOS OBJECTOS

vez, cada uma destas classes ir possuir os seus dados e mtodos. A este tipo de relao chama-se composio, sendo a relao mais tpica do design orientado aos objectos. A linha com um quadrado numa das pontas indica uma relao de composio, estando o losango do lado da classe que contm uma referncia para a outra.

Figura 3.3 Relao de composio

No entanto, existe um outro tipo de relao bastante comum e muito importante, a relao de herana. Consideremos ainda o exemplo da classe Empregado. Imaginemos agora que numa aplicao que utilize esta classe surge uma nova classe que representa o patro da empresa. Isto , existe uma classe Patrao. Tal como um empregado normal, o patro possui um nome e uma idade. No entanto, possui ainda uma caracterstica que ter um certo nmero de aces da empresa. Uma possvel soluo para este problema seria criar uma nova classe que tivesse como campos o nome, a idade e o nmero de aces que o patro possui. No entanto, iramos tambm de ter de duplicar os mtodos existentes, para alm dos dados j presentes em Empregado. Uma outra possvel soluo seria utilizar composio e colocar dentro da classe Patrao uma instncia de Empregado. No entanto, novamente aqui temos o problema de ter de duplicar os mtodos de Empregado na classe Patrao. Quando surge este tipo de problemas, em que uma classe uma especializao de uma outra (Patrao um caso especial de Empregado: o patro um empregado da empresa), estamos na presena de uma relao de herana. Isto , existe uma classe que possui todos os elementos que outra possui, mas tambm possui mais alguns, sejam estes mtodos ou dados. No nosso exemplo particular, dizemos que Patrao uma classe derivada (ou herdada) da classe Empregado (figura 3.4). A seta indica a relao de herana, indo da classe derivada para a classe base.

FCA - Editora de Informtica

49

C# 2.0

Figura 3.4 Relao de herana

Tambm vulgar chamar classe Empregado classe base, uma vez que est a ser utilizada como base de uma outra classe que se est a definir. Vejamos como representada esta relao:
class Patrao : Empregado { private int NumeroAccoes; // Nmero de aces da empresa

public Patrao(string nomeDoPatrao, int idadeDoPatrao, int nAccoes) : base(nomeDoPatrao, idadeDoPatrao) { NumeroAccoes = nAccoes; } // Mostra o nmero de aces do patro public void MostraAccoes() { Console.WriteLine("O nmero de aces : {0}", NumeroAccoes); } }

A primeira mudana aparente na declarao da classe:


class Patrao : Empregado { ... }

o que isto quer dizer que a classe Patrao deriva de Empregado, tendo todas as variveis e mtodos presentes na classe base (Empregado). Note-se tambm a modificao no construtor:
public Patrao(string nomeDoPatrao, int idadeDoPatrao, int nAccoes) : base(nomeDoPatrao, idadeDoPatrao) { ... }

Como a classe diferente, o construtor tambm tem de ser diferente. Aps a declarao do construtor, indicado aps os dois pontos a forma como a classe base tem de ser construda. Isto , antes de um patro ser um patro, tem de ser um empregado. Assim, a palavra-chave base representa o construtor da classe acima (Empregado). Neste caso
50
FCA - Editora de Informtica

CONCEITOS DE ORIENTAO AOS OBJECTOS

indicado que o objecto base Empregado deve ser inicializado com as variveis nomeDoPatrao e idadeDoPatrao. Finalmente, no corpo do construtor propriamente dito, feita a inicializao da varivel que faltava (NumeroAccoes).
Empregado,

Um ponto extremamente relevante que um objecto Patrao tambm um objecto possuindo todos os mtodos que este tem. Assim, o seguinte cdigo perfeitamente vlido:

Patrao donoDaEmpresa = new Patrao("Manuel Marques", 61, 1000000); donoDaEmpresa.MostraInformacao(); donoDaEmpresa.MostraAccoes();

de salientar que na maioria das aplicaes no existem muitas relaes de herana. As relaes de herana so extremamente teis quanto se est a desenvolver bibliotecas para serem utilizadas (ou reutilizadas) por outros. Um erro muito comum das pessoas que se encontram a aprender OOP pela primeira vez pensarem que a herana tem de, forosamente, ser utilizada na soluo de todos os problemas. Isso no verdade. S se deve utilizar herana em casos em que traga vantagens claras de reutilizao ou caso a abstraco seja de facto algo que seja bem implementado em objectos concretos derivados.

Figura 3.5 Exemplo de uma hierarquia de classes

Uma das regras bsicas para determinar se uma relao de composio ou de herana perguntar se se deve dizer contm ou um. Por exemplo: um automvel contm um motor, logo, deve existir uma relao de composio entre automvel e motor. No se pode dizer que um automvel um motor. Da mesma forma, pode-se dizer que um automvel um veculo. Assim, existe uma relao de herana entre estas duas entidades. No faz sentido dizer que um veculo contm um automvel.

FCA - Editora de Informtica

51

C# 2.0

Sempre que o programador decidir ter uma classe base e vrias classes derivadas, dever mover o mximo de funcionalidade para a classe base. Por exemplo, se existirem variveis com a mesma funcionalidade nas classes derivadas, estas devero ser substitudas por uma varivel comum na classe base. O mesmo acontece com mtodos semelhantes. tpico existir uma classe base, da qual derivam vrias outras classes. Ao conjunto de classes pertencentes mesma rvore, chama-se hierarquia de classes. A figura 3.5 ilustra parte de uma hierarquia de classes retirada da documentao da plataforma .NET.

3.4 Polimorfismo
Uma outra caracterstica fundamental da programao orientada aos objectos o polimorfismo. Por polimorfismo, entende-se a capacidade de objectos diferentes se comportarem de forma diferente quando lhes chamado o mesmo mtodo. Vejamos um caso concreto.
/* * Programa que ilustra o conceito de polimorfismo. */ using System; // Classe base, comum a todos os empregados class Empregado { private string Nome; public Empregado(string nomeDaPessoa) { Nome = nomeDaPessoa; } public void MostraNome() { Console.WriteLine("{0}", Nome); } // Mtodo preparado para ser alterado por classes derivadas public virtual void MostraFuncao() { Console.WriteLine("Empregado"); }

// Classe patrao, um caso especial de empregado class Patrao : Empregado { public Patrao(string nomeDoPatrao) : base(nomeDoPatrao) { } // Nova implementao da funcionalidade "MostraFuncao" public override void MostraFuncao() { Console.WriteLine("Patrao");
52
FCA - Editora de Informtica

CONCEITOS DE ORIENTAO AOS OBJECTOS }

// O programa principal class Exemplo3_1 { static void Main() { // Uma pequena tabela dos trabalhadores da empresa Empregado[] trabalhadores = new Empregado[] { new Empregado("Z Maria"), new Empregado("Antnio Carlos"), new Patrao("Jos Antnio") }; // Mostra o nome e a funo de todos os trabalhadores for (int i=0; i<trabalhadores.Length; i++) { trabalhadores[i].MostraNome(); trabalhadores[i].MostraFuncao(); Console.WriteLine(); }

} }

Listagem 3.1 Programa que ilustra o conceito de polimorfismo (ExemploCap3_1.cs)

No caso do programa da listagem 3.1, temos uma classe base Empregado e uma classe derivada Patrao. Existe ainda um mtodo chamado MostraFuncao() que, por omisso, diz que a pessoa um Empregado. No entanto, as classes derivadas devem poder modificar este mtodo para que reflictam a funo da pessoa em questo. Assim, enquanto no caso de um empregado simples o mtodo mostra a palavra Empregado, no caso do patro dever mostrar Patro. Suponhamos que temos o seguinte cdigo:
Patrao chefe = new Patrao("Manuel Marques"); chefe.MostraNome(); chefe.MostraFuncao(); Empregado emp = chefe; emp.MostraFuncao();

Qual

dever

ser

resultado

da

chefe.MostraFuncao(); levar a que seja uma referncia Empregado emp com o valor

execuo? Obviamente que a linha escrito Patro, no entanto, quando se cria de chefe e se chama MostraFuncao() sobre

esta, o que acontecer? Em primeiro lugar, a converso de Patrao em Empregado possvel. sempre possvel converter (ou utilizar) uma classe base em vez da classe derivada. Isso deve-se ao facto de uma relao de herana ser uma relao um. A classe Patrao possui todos os elementos que a classe Empregado possui.
FCA - Editora de Informtica

53

C# 2.0

Agora vem a parte mais interessante: ao escrever emp.MostraFuncao();, o CLR guarda a verdadeira identidade dos objectos que esto associados a cada referncia. Assim, embora estejamos a chamar o mtodo MostraFuncao() atravs de uma referncia Empregado, o sistema sabe que tem de chamar a verdadeira implementao desse mtodo, para o objecto em causa. Neste caso o resultado da execuo seria ento:
Manuel Marques Patro Patro

A isto chama-se polimorfismo. O sistema descobre automaticamente a verdadeira classe de cada objecto e chama as implementaes reais para os objectos em causa. Em C#, sempre que se quiser tirar partido desta funcionalidade, tem de se declarar o mtodo base como sendo virtual (chama-se a isto mtodos virtuais). Sempre que numa classe derivada se altera a implementao de um destes mtodos, como o caso da classe Patrao, tem de se marcar esse mtodo com a palavra-chave override. Voltemos agora ao exemplo da listagem 3.1. Na classe principal do programa criada uma pequena tabela com os trabalhadores da empresa (trabalhadores), onde se encontram dois empregados normais e um patro. Em seguida, executado o seguinte ciclo:
for (int i=0; i<trabalhadores.Length; i++) { trabalhadores[i].MostraNome(); trabalhadores[i].MostraFuncao(); Console.WriteLine(); }

Aqui vemos o poder do polimorfismo em aco. Os empregados (quer sejam normais ou patres) so tratados de forma uniforme, sendo colocados numa tabela. No entanto, ao chamar o mtodo MostraFuncao(), no caso dos empregados normais, mostrado Empregado. No caso dos patres mostrado Patro. O resultado da execuo do programa o seguinte:
Z Maria Empregado Antnio Carlos Empregado Jos Antnio Patro

O polimorfismo permite que os objectos mantenham a sua identidade apesar de serem tratados usando classes mais genricas (isto , classes mais acima na hierarquia de derivao). Isso extremamente poderoso. Por exemplo, neste exemplo seria trivial estend-lo por forma a que houvesse um mtodo de clculo de salrio que no caso dos empregados teria uma certa implementao e no caso dos patres uma outra. Convm alertar para o facto de que no caso de no se declararem os mtodos como virtual ou no se diga que os novos mtodos so override, o comportamento do sistema
54
FCA - Editora de Informtica

CONCEITOS DE ORIENTAO AOS OBJECTOS

chamar os mtodos da classe que est a ser utilizada como referncia. Isto , no pequeno exemplo de chefe, ao fazer emp.MostraFuncao();, caso MostraFuncao() no fosse um mtodo virtual ou a nova implementao no fizesse o override da antiga, a chamada resultaria em Empregado em vez de Patro. Isto uma fonte comum de erros, pelo que o programador deve estar atento a esta situao.

A reter
Conceitos bsicos de OOP

A programao orientada aos objectos (OOP) baseia-se em trs princpios bsicos: encapsulamento, composio/herana e polimorfismo. Encapsulamento refere-se ao facto de as estruturas de dados serem entidades privadas de cada classe, devendo ser apenas acedidas por elementos da prpria classe. Composio e herana so os tipos de relaes que podem existir entre objectos (e classes). Composio corresponde a relaes do tipo contm, herana corresponde a relaes do tipo um. Polimorfismo refere-se capacidade de diferentes objectos se comportarem de forma diferente quando o mesmo mtodo invocado neles. Isto apesar de ser utilizada uma referncia para uma classe base para fazer a chamada. Uma classe representa uma famlia de objectos, enquanto um objecto representa uma instncia dessa famlia (ex: Empregado uma classe enquanto a entidade que representa Jos Antnio um objecto da classe Empregado). Diferentes instncias de uma classe tm variveis diferentes. As instncias so criadas com o operador new. Ao criar um novo objecto, o construtor da classe chamado. O construtor tem o mesmo nome que a classe e no tem valor de retorno. Se um elemento de uma classe declarado para elementos dessa classe. Se um elemento de uma classe declarado exterior da classe.
private, public,

ento visvel apenas ento visvel para o

Os dados da classe devem, regra geral, ser privados. Apenas o menor nmero possvel de mtodos da classe deve ser pblico. Uma relao de composio surge quando uma classe tem de conter um objecto de uma outra classe (exemplo: automvel contm motor). Uma relao de herana surge quando um objecto tambm uma instncia de uma outra classe mais geral (exemplo: automvel um veculo). Uma relao de herana indica-se por:
class ClasseDerivada : ClasseBase { ... }

sempre possvel utilizar uma referncia de uma classe mais acima na hierarquia de derivao para um objecto de uma classe derivada dessa. Para existir polimorfismo, os mtodos na classe base tm de ser declarados virtual e nas classes derivadas tm de ser declarados override.

Ao longo dos prximos captulos, iremos analisar detalhadamente os pormenores associados programao orientada aos objectos.
FCA - Editora de Informtica

55

Você também pode gostar