
APENDICE I - oop object-oriented programming

  Programao orientada para objetos (OOP)
  Recentemente, tem surgido uma nova palavra no vocabulrio de analistas
e programadores: OOP.
   O crescente entusiasmo por esta metodologia de engenharia de software
tem alterado a vida de todos ns neste ltimos tempos.
  Mas, o que  programao orientada para objetos (OOP)?
  OOP no  nehuma nova "bruxaria" de algum Einstein da  informtica,  e
sim apenas um jeito diferente de enxergar a programao como um todo.
  Foi idealizada  a  partir  da  observao  de  como  os  programas  se
comportam diante das tarefas que eles tem que executar e raramente surge
um "amor a primeira vista" entre um programador experiente e  este  novo
coneito,  pois,  OOP,  de  certa  forma,  vai  de  desencontro  ao   que
considervamos padro em matria de programao.
  Ela  surgiu  nos  anos  70,  com  a  linguagem  Simula  (linguagem  de
simulao) e observou-se que os conceitos de programao orientada  para
objetos poderaim ser utilizados com um propstio mais agrangente do  que
apenas como meio de pesquisa e simulaes.
  Devido a isto, vrios anos depois (fim dos anos 80), ela comeou a  se
tornar  popular  e  alguns  fabricantes,  como  a  Borland,    decidiram
incorpor-la a seus produtos.
  Hoje, sem dvida  alguma,  ela  promete  ser  to  importante  para  o
desenvolvimento e  programao  de  softwares  como  foi  a  programao
estruturada na dcada passada.
  Para o Pascsal, ela surgiu na verso 5.5  do  Turbo  Pascal,  passando
rapidamente para a verso 6.0, onde no somente foi refinada mas  tambm
utilizada como ferramenta no desenvolvimento do novo ambiente  integrado
(IDE) atravs da biblioteca Turbo Vision.
  Atualmente encontram-se inmeras linguagens que colocam    disposio
dos programadores OOP, como por exemplo a linguagem C e  at  o  imortal
Cobol na sua verso para microcomputadores.
  Hoje, os programadores de Pascal, contam  com  produtos  como  o  novo
Turbo Pascal 7.0, o Borland  Pascal  e  o  Turbo  Pascal  para  Windows,
ferramenta de alta produtividade  e  de  grande  refinamento  tcnico  e
visual.
  O que mudou?
  A caracterstica marcante de OOP  que dentro  de  um  objeto  podemos
encontrar os dados juntamente com os procedimentos que os manipulam.
  Nossos programas, at agora, se pareciam com isso: TYPE
  registro = RECORD
    x : REAL;
    y : REAL;
  END; VAR
  reg : registro; PROCEDURE incio(a,b : REAL); BEGIN
  REG.X :=a;
  reg.y :=  b; END; BEGIN
  incio (10,05);
  WRITELN(reg.x);
  WRITELN(reg.y); END.
    Com OOP eles ficariam assim:  TYPE
  tipooop : OBJECT
  x : REAL;
  y : REAL; PROCEDURE inicializavariveis(A,B : REAL); FUNCTION pegax  :
REAL;    FUNCTION    pegay    :       REAL;        END;        PROCEDURE
tipooop.inicializavariveis(A,B : REAL); BEGIN
  x := A;
  y := B; END; FUNCTION tipooop.pegax : REAL; BEGIN
  pegax := x; END; FUNCTION tipoop.pegay : REAL; BEGIN
  pegay := y; END; VAR
  voop : TIPOOOP; BEGIN
  voop.inicializavariveis(10, 05);
  WRITELN(VOOP.pegax);
  WRITELN(voop.pegay); END.

  Neste exemplo,  podemos observar que ele possui duas variveis :  x  e
y.
  Os procedimentos inicializavariveis,  pegax e pegay so  encarregados
de acessar estas  variveis  e  manipular  seu  contedo  conforme  suas
necessidades.
   importante se ter em mente que  uma boa prtica de  programao  em
OOp, manter a integridade do objeto, atribuindo  a  responsabilidade  de
manipular as variveis aos procedimentos do prprio objeto.
  Esta estrutura facilita a manuteno do sistema uma vez que o objeto 
um conjunto independente.
  Como mostraremos a seguir, as variveis x  e  y  podem  ser  acessadas
diretamente de outros pontos, externos ao objeto, mas isto  s  tende  a
dificultar a lgica geral do  sistema,  o  que  vai  ao  desencontro  do
objetivo principal deste tipo de programao. TYPE
  tipooop_errado = OBJECT
  x : REAL;
  y : REAL; PROCEDURE inicializavariveis(A,B : REAL;);  END;  PROCEDURE
tipoop_errado.inicializavariveis(A,B : REAL); BEGIN
  x := A;
  y := B; END; VAR
  voop_errado : TIPOOOP_ERRADO; PROCEDURE mostravariveis; BEGIN
  WRITELN(voop_errado.x);
  WRITELN(voop_errado.y); END; BEGIN
  voop_errado.inicializavariveis(10,05);
  mostravariveis; END.

  Conceitos principais.

  Existem 3 conceitos bsicos e fundamentais que so: - encapsulamento:
   o exemplo a seguir, ilustra  uma  estrutura  encapsulada.  tabela  de
caracteres
  - controle
  - numricos
  - alfabticos maisculas vogais consoantes
                minsculas vogais e consoantes
  - outros
  - caracteres especiais
  em termos de OOP, o nvel tabela de caracteres  representa  o  prprio
objeto. Podemos observar que dentro da tabela de caracteres  encontramos
diversos subconjuntos (controle, numricos, alfabticos, etc.) e  dentro
de alguns deles, por sua vez, mais subconjuntos.
  Em termos de programao, esta estrutura se pareceria com algo  assim:
TYPE
  ttabeladecaracteres = OBJECT
    caracteres : ARRAY[0..266] OF CHAR;
    PROCEDURE inicializatabela;
    PROCEDURE mostracontrole;  {de 0 at 31}
    PRCEDURE mostranumricos;  {de 48 at 57}
    {...}
  END;

- hereditariedade: define o "parentesco" atribuido ao objeto em questo.
  Objetos  definidos  desta  forma  possuem  todas  as    variveis    e
procedimentos do objeto referenciado:

  Vejamos como fica este tipo de  estrutura  com  um  exemplo  completo.
PROGRAM ex01; TYPE
  ttiposomaoop = OBJECT
    x : REAL;
    y : REAL;
    somatria: REAL;
    PROCEDURE init(A,B : REAL);
    PROCEDURE soma;
    FUNCTION  pegavalordasoma   :    REAL;    END;    ttipomdiaoop    =
OBJECT(ttiposomaoop)
    mdia : REAL;
    PROCEDURE calculaamedia;  FUNCTION  pegavalordamdia  :  REAL;  END;
{ttiposomaoop} PROCEDURE ttiposomaoop.init(A,B : REAL); BEGIN
  x := A;  {atualiza as variveis do objeto}
  y := B;
  soma;  {efetua a somatria} END; PROCEDURE ttiposomaoop.soma; BEGIN
  somatria :=  x +  y;  END;  FUNCTION  ttiposomaoop.pegavalordasoma  :
REAL; BEGIN
  pegavalordasoma := somatria;  {devolve o valor da soma} END;
        {tipomediaoop} PROCEDURE ttipomediaoop.calculaamedia; BEGIN
  media := somatria / 2; END; FUNCTION ttipomediaoop.pegavalordamedia :
REAL; BEGIN
  pegavalordamedia := media;  {devolve o valor da media} END; VAR
  media : TTIPOMEDIAOOP;
  a, b : REAL; BEGIN
  WRITELN;
  READLN(A);
  READLN(b);  {recebe valores do usurio}
  media.init(a, b);  {alimenta as variveis}
        {internas e calcula a soma}
        {mostra seu valor}
  WRITELN(o valor da somatria  de  x  e  y  :,media.pegavalordasoma:
4:2);
  media.calculaamedia; {calcula o valor da media}
        {mostra o valor da media}
  WRITELN(o valor da media de x e y :,media.pegavalordamedia:4:2);
  READLN; END.

No exemplo anterior, ttipomediaoop contem por hereditariedade  todas  as
variveis e procedimentos de ttiposomaoop.
  Nele foi definida a varivel mdia do tipo  Ttipomediaoop  para  poder
receber  os  valores  a  serem  somados   (atraves    do    procedimento
Ttiposomaoop.init)  e    assim    pelo    procedimento    Ttipomediaoop.
Calculaamdia efetivamente realizar  o  calculo  final.  Observao:  na
definio deste tipo de estrutura,    altamente  desejvel  uma  prvia
anlise dos dados e procedimentos envolvidos para que os tipos  "filhos"
no tenmham que executar tarefas desnecessrias.

- polimorfismo: refere-se  aptido, dos procedimentos de um objeto tipo
"filho", de redefinir os procedimentos do objeto "pai".
  Este  pequeno  programa  ilustrativo  recebe  do  usurio  uma  string
qualquer, mostra-a na linha abaixo e  a  partir  da  mesma  movimenta  o
cursor pela linha at a coluna 80 do vdeo e retorna  pela  mesma  linha
at a primeira coluna.
  Analise cuidadosamente o corpo do programa. PROGRAM  ex02;  USES  CRT;
TYPE
  str20 = STRING[20];
  pmovecursor = TMOVECURSOR;  {ponteiro ao objeto  tmovecursor}
  tmovecursor = OBJECT;
    col : BYTE;
    msg : STR20;
    constructor init(m: str20); {inicializa as variveis e  posiciona  o
cursor}
    PROCEDURE movecursor; VIRTUAL;  {desloca o cursor para a direita}
    DESTRUCTOR DONE; virtual; {conclue o objeto}
  END;
  PMOVEAOCONTRARIO = TMOVEAOCONTRARIO; {ponteiro ao objeto}
  TMOVEAOCONTRARIO = OBJECT; {tmovecursor}
        {referenciado ao objeto "pai" tmovecursor}
    PROCEDURE movecursor;  virtual;  {desloca  o  cursor  para  esquerda
apagando}
    DESTRUCTOR DONE, VIRTUAL; {conclue o objeto}
  END;
    {tmovecursor}
  CONSTRUCTOR TMOVECURSOR.INIT; BEGIN
  msg := m;
  WRITELN;
  WRITE(msg,: );
  col := wherex;
  movecursor; {move cursor para a  direita  ou  esquerda  dependendo  da
chamada} END; PROCEDURE tmovecursor.movecursor; VAR
  lin : BYTE; BEGIN
  lin := WHEREY;
  WHILE col <79 DO
    BEGIN
      INC(col, 1);
      GOTOXY(col1,lin);
      DELAY(80);
    END; {WHILE} END; DESTRUCTOR TMOVECURSOR.DONE; BEGIN
  WRITELN;
  WRITELN(fim do exemplo...); END;
    {tmoveaocontrario} PROCEDUREtmoveaocontrario.movecursor; VAR
  lin : BYTE; BEGIN
  {$IFDEF VER70}
  INHERITEDMOVECURSOR;
  {$ELSE}
  Tmovecursor.movecursor;
  {$endif}
  lin := wherey;
  WHILE co1 >1 DO
    BEGIN
      DEC(co1,1);
      GOTOXY(co1,lin);
      WRITE( );
      DELAY(80);
    END; {WHILE} END; DESTRUCTOR TMOVEAOCONTRARIO.DONE; BEGIN
  {4IFDEF VER70}
  INHERITED DONE;
  {$ELSE}
  Tmovecursor.done;
  {$ENDIF}
  WRITE(#7); END; VAR
  mensagem : STRING;
  virtualtest : TMOVECURSOR; {cria varivel objeto} BEGIN
  READLN(mensagem);
  VIRTUALTEST := NEW(TMOVEAOCONTRARIO,INIT(mensagem));
        {aloca memria para o ponteiro do objeto}
  DISPOSE(virtualtest, done); {desaolca  a  memria  do  objeto  alocada
anteriormente} END.

  no exemplo EX 02, o procedimento movecursor do objeto tmoveaocontrario
executa a mesma tarefa do procedimento movecursor do objeto  tmovecursor
(deslocamento  para  a  adireita),  adicionando  o  movimento    inverso
(deslocamento para a esquerda).
  Mas a respeito de OOp.
  continuemos analisando o exemplo EX02.
  Logo acima da definio do objeto  tmovecursor,  encontramos  a  linha
pmovecursor = tmovecursor isto significa que pmovecursor  um  ponteiro
do tipo objeto tmovecursor. Este tipo de  definio  funciona  de  forma
idntica s variveis dinmicas que voc j deve ter utilizado para, por
exemplo, fazer uma lista ligada de registro em memria.
  Se utilizarmos uma varivel do tipo tmovecursor, estaremos trabalhando
com ela de  forma  esttica,  ou  seja,  os  procedimentos  e  variveis
contidos no objeto  sero  introduzidos  pelo  compilador  em  tempo  de
compilao e j constaro  no  arquivo  .EXE,  quando  voc  executar  o
programa.
  Por outro lado,  se  definirmos  uma  varivel  do  tipo  pmovecursor,
estaremos "dizendo" ao compilador que ela ser  "montada"  em  tempo  de
execuo, ou seja, quando ela for utilizada devemos alocar uma  rea  no
heap (memria), tipicamente atravs do comando NEW, que  ser  discutido
em breve, Este objeto ser chamado de virtual.
  Uma vez definido este procedimento como virtual esta palavra reservada
dever sempre acompanhar as redefinies do prprio (veja  na  definio
do procedimento movecursor).
  Dentro da definio do objeto tmovecursor, voc dever ter notado  que
o procedimento init est precedido pela palavra reservada CONSTRUCTOR.
  O procedimento constructor tem  por  finalidade  realizar  as  tarefas
inicializao  da  VMT  (virtual  memory  table  ou  tabela  virtual  de
memria), e como seu nome indica deve ser, sempre, utilizado em primeiro
lugar em objetos que contenham mtodos virtuais. Se voc no inicializar
um objeto virtual com o procedimento CONSTRUCTOR, o compilador no  ter
como determinar a sequncia correta dos mtodos  virtuais  e  isto  ter
resultados imprevisveis dentro de sua aplicao.
  Tipicamente,  voc  ter  um  procedimento  CONSTRUCTOR  associado  ao
comando NEW.
  O comando NEW tem sido implementado de  forma  a  poder,  no  apenas,
alocar memria para um objeto mas tambm para  executar  um  determinado
mtodo. No EX02, o mtodo em questo   o  init.  Ele  se  encarrega  de
inicializar as variveis do  objeto  e  providencia  a  movimentao  do
cursor.
  De forma semelhante ao comando NEW, o DISPOSE, tambm foi acrecido  de
um eventual parmetro. Nesse exemplo, colocamos o procedimento done.
  Repare que na declarao do procedimeno, consta uma outra nova palavra
reservada, DISPOSE.
  O DISPOSE tem a funo contrria ao constructor mas no   obrigatria
sua presena mesmo em objetos que tenham  mtodos  virtuais.  Dentro  do
programa foi colocado para  exemplificar  e  mostrar  sua  utilidade  em
objetos que possuem caractersticas polifrmicas.
  Para o fim deixamos o comando INHERITED  o  qual  foi  implementado  a
partir da verso 7.0 do Turbo Pascal.
  Mtodos virtuais as vezes, como no exemplo  anterior,  necessitam  das
tarefas  que  seu  "pai"  executa.  Vejamos  o   procedimento    virutal
tmoveaocontrario,movecursor. Ele  "chama"  o  procedimento  homnimo  do
objeto  "pai"   (INHERITEDmovecursor    para    a    verso    7.0    ou
tmovecursor.movecursor que  universal) e acrecenta o retorno do cursor.
Desta forma podemos alterar ou implementar de  forma  fcil  e  elegante
novas tarefas a um mtodo, reutilizando o cdigo  previamente  definido,
sem ter que partir para complicados artifcios.
   Para exemplificar de forma  prtica,  altere  a  linha  onde  se  l:
virtualtest := new(pmoveaocontrario,init(mensagem)); por virtualtest  :=
NEW(pmovecursor,init(mensagem));
  D esta forma voc ver que o cursor apenas ser deslocado at a coluna
80 e no mais retornar como era feito originalmente.
  Esperamos que estas dicas tenham lhes dado  uma  pequena  amostra  das
inmeras aplicaes que este tipo de programao pode oferecer  e  tenha
sempre em mente que: se voc pretende programar um Turbo Vision ou Turbo
Pascal para Windows, este conceitos sero  de  tamanha  importncia  que
ser virtualmente impossvel continuar sem eles.
