e-mail    Debatní kniha    Mapa stránek    Hlavní  
 INT21h 
 
Pseudopole v pascalu

Co je pole, je jasné. Pascal ale zná i tzv. pseudopole. Z klasického Turbo pascalu určitě znáte pseudopole Port a PortW.Zde je na místě otázka, co je to vlastně zač. Není to blok paměti, alejakýsi virtualizovaný přístup ke skrytým procedurám. To může býtužitečné i v mnoha jiných případech, ale bohužel, Turbo pascalneumožňuje tvořit si vlastní pseudopole. To je rys, pro který bývápascal vysmívaný programátory jiných jazyků, tedy, že programátornemůže vytvořit analogie některých zabudovaných konstrukcí. A z tohoodvozují, že pascal není plnohodnotný programovací jazyk. To jesamozřejmě nesmysl a navíc pro Freepascal neplatí ani první částnámitky. Ve Freepascalu totiž je možné tvořit vlastní pseudopole a umíto obě generace: 1.x.x i 2.x.x.

Pseudoproměnné


Než se pustíme do pseudopolí, začneme trochu jednoduššímipseudoproměnnými. Pozadí této syntaxe je dosti složité a v tomto článkuse nebudu pouštět do rozsáhlého výkladu a omezím se jen na minimum.Teorii a systematický výklad syntaxe si můžete přečíst z manuálu kFreepascalu nebo z jakékoliv lepší knihy o Delphi.
Pseudoproměnné jsou odvozeny od jedné vlastnosti tříd z objektového programování. Přípomeňme si, že TP i BP znají tzv. objekty,což je seskupení procedur, funkcí a proměnných, ve kterých procedury afunkce objektu společně sdílí proměnné objektu. Freepascal (a Delphi)kromě objektů znají i třídy (class), které koncept objektů v různých aspektech rozšířují. Jedním z rozšíření jsou tzv. properties, což se do češtiny překládá jako vlastnosti.
Ukažme si prográmek:
{$MODE OBJFPC}         {Nutno zapnout budto takto nebo pomoci nastaveni v menu}
type TTrida = class
     public
        Procedure PriradCislo(i:longint);
        Function ZjistiCislo:longint;
        property cislo:longint read ZjistiCislo write PriradCislo;

     protected
        vnitrnicislo:shortint;
     end;

Procedure TTrida.PriradCislo(i:longint);
begin
if i<(-128) then i:=-128;
if i>127 then i:=127;
vnitrnicislo:=i;
end;

Function TTrida.ZjistiCislo:longint;
begin
ZjistiCislo:=vnitrnicislo;
end;

var trida:TTrida;
begin
trida:=TTrida.Create;
trida.cislo:=4543;
writeln(trida.cislo);
readln;
end.
Před sebou máme ne zcela triviální kód, který přiřadí proměnné vnitrnicislo hodnotu. Možná se ptáte, proč to dělat tak složitě, když by prostě stačilo ponechat vnitrnicislo v režimu public a provést přiřazení:
trida.vnitrnicislo:=HODNOTA
No jo, jenže všimněte si, že vnitrnicisloje jenom shortint a lehko bychom mohli přiřadit hodnotu mimo rozsah,což by vedlo k neočekávanému chování programu. Oklika přes pseudoproměnnou cislo umožňuje provést kontrolu rozsahu a podobným věcem zamezit. A nejen to. Obsah obslužných funkcí PriradCislo a ZjistiCislomůže být libovolný a zdaleka se nemusí jen omezovat na kontrolyrozsahů. Jako dobrý způsob použití mě napadá ukládání přiřazovanýchhodnot do logovacího souboru, což by umožňovalo snadnější analýzu chyb.

Pseudopole


Pseudopole jsou dalším drobným rozšířením vymoženosti property, potažmo pseudoproměnných. Bez dlouhých řečí si ukažme kód, který se podobá standardní pascalovské definici pseudopole Port
{$MODE OBJFPC}
{$CALLING OLDFPCCALL}
type TBrana = class
     public
        Procedure DoPortu(p:word;b:byte);
        Function ZPortu(p:word):byte;
        property B[p:word]:byte read ZPortu write Doportu;
     end;

Procedure TBrana.DoPortu(p:word;b:byte);assembler;
asm
mov dx,p
mov al,b
out dx,al
end;

Function TBrana.ZPortu(p:word):byte;assembler;
asm
mov dx,p
in al,dx
end;

var brana:TBrana;
    i:longint;
    a:byte;
begin
brana:=TBrana.Create; {ve skutecnosti neni nutne, nebot nepristupujeme k zadnym datum tridy}

writeln('Po zmacknuti Enteru program pocka 700 snimkovych behu, tedy 10 sekund');
readln;
writeln('Start!');
for i:=1 to 700 do
    begin
    while Brana.B[$3da] and 8 <> 0 do;
    while Brana.B[$3da] and 8 = 0 do;
    end;
writeln('Cas uplynul!');
readln;
end.
Docela se to už podobá pascalovskému pseudopoli Port, že? Ale jak odstranit ono ohyzné "Brana.B" a nahradit to prostým "Brana"? Jde to? Ano, jde.
Do deklarace property jde totiž vsunout kouzelný modifikátor default, který umožní vynechat část ".B"
Takže do třetice krátký prográmek, který připraví pseudopole přesnětak, jak jsme zvyklí. Opakovat příklad z porty by ale bylo nudné, takžesi ukážeme, jak virtualizovat obrazovku do dvourozměrného pseudopole, apřipomeneme si, jak ve Freepascalu provést přímý zápis do videopaměti.
{$MODE OBJFPC}
const SIRKAOBRAZOVKY:longint = 80;
      VYSKAOBRAZOVKY:longint = 25;

type
     TObr = class
     private
        Function RozsahOK(x,y:byte):boolean;
        Procedure ZapisZnak(x,y:byte;c:char);
        Function PrectiZnak(x,y:byte):char;
     public
        property ZZ[x,y:byte]:char read PrectiZnak write ZapisZnak;default;
        end;

Function TObr.RozsahOK(x,y:byte):boolean;
begin
RozsahOK:=(x>0) and (y>0) and (x<=SIRKAOBRAZOVKY) and (y<=VYSKAOBRAZOVKY);
end;

Procedure TObr.ZapisZnak(x,y:byte;c:char);
begin
if RozsahOK(x,y) then
   asm
   movzx ebx,y
   movzx eax,x
   dec ebx
   dec eax
   imul ebx,SIRKAOBRAZOVKY
   add ebx,eax
   shl ebx,1
   add ebx,0B8000h
   mov al,c
   mov fs:[ebx],al
   end;
end;

Function TObr.PrectiZnak(x,y:byte):char;
begin
if RozsahOK(x,y) then
   asm
   movzx ebx,y
   movzx eax,x
   dec ebx
   dec eax
   imul ebx,SIRKAOBRAZOVKY
   add ebx,eax
   shl ebx,1
   add ebx,0B8000h
   mov al,fs:[ebx]
   end;
end;

var Obr:TObr;
    x,y:byte;
    
begin
{Obr:=TObr.Create}   {neni treba, protoze neprisupuji k promennym tridy}
for y:=10 to 20 do
    for x:=20 to 60 do
        Obr[x,y]:='*';  {Mozno i Obr.ZZ[x,y]:='*'  (ale proc tak osklive?)}
readln;
end.
Properties mají pochopitelně mnohem širší použití než jen tvorbapsedopolí. Velice užiteční jsou například v tvorbě užívatelskýchrozhraní (GUI), kdy je jejich pomocí možné dosáhnout toho aby se přizměně parametrů grafického prvku změna okamžitě projevila na obrazovce.Například zavoláním...

Tlacitko.text:='zmeneny text';

...patřičně obaleným v properties dosáhneme toho, aby měnící procedura rovnou zavolala Tlacitko.Draw a změna se tak ihned projevila na obrazovce.

A to je vše.



Pascal - hlavní
Překladače
Vlastní články
Převzaté články
Věci na stáhnutí
Odkazy k tématu
BP7 buglist
Chyba Run-time 200

BASIC