Pascal - Object Oriented

Possiamo immaginare il nostro universo fatto di diversi oggetti come il sole, la terra, la luna, ecc. Allo stesso modo, possiamo immaginare la nostra macchina fatta di diversi oggetti come il volante, lo sterzo, il cambio, ecc. Allo stesso modo, ci sono concetti di programmazione orientata agli oggetti, che assumere tutto come un oggetto e implementare un software utilizzando oggetti diversi. In Pascal, ci sono due tipi di dati strutturali usati per implementare un oggetto del mondo reale:

  • Tipi di oggetti
  • Tipi di classe

Concetti orientati agli oggetti

Prima di entrare nei dettagli, definiamo importanti termini Pascal relativi a Pascal orientato agli oggetti.

  • Object- Un oggetto è un tipo speciale di record che contiene campi come un record; tuttavia, a differenza dei record, gli oggetti contengono procedure e funzioni come parte dell'oggetto. Queste procedure e funzioni vengono mantenute come puntatori ai metodi associati al tipo di oggetto.

  • Class- Una classe è definita quasi allo stesso modo di un oggetto, ma c'è una differenza nel modo in cui vengono create. La Classe è allocata sull'Heap di un programma, mentre l'Oggetto è allocato sullo Stack. È un puntatore all'oggetto, non all'oggetto stesso.

  • Instantiation of a class- Istanziazione significa creare una variabile di quel tipo di classe. Poiché una classe è solo un puntatore, quando viene dichiarata una variabile di un tipo di classe, la memoria è allocata solo per il puntatore, non per l'intero oggetto. Solo quando viene creata un'istanza utilizzando uno dei suoi costruttori, la memoria viene allocata per l'oggetto. Le istanze di una classe sono anche chiamate "oggetti", ma non confonderle con Object Pascal Objects. In questo tutorial, scriveremo "Object" per Pascal Objects e "object" per l'oggetto concettuale o l'istanza di classe.

  • Member Variables - Queste sono le variabili definite all'interno di una Classe o di un Oggetto.

  • Member Functions - Queste sono le funzioni o le procedure definite all'interno di una Classe o di un Oggetto e vengono utilizzate per accedere ai dati dell'oggetto.

  • Visibility of Members- I membri di un oggetto o di una classe sono anche chiamati campi. Questi campi hanno visibilità diverse. La visibilità si riferisce all'accessibilità dei membri, cioè esattamente dove questi membri saranno accessibili. Gli oggetti hanno tre livelli di visibilità: pubblico, privato e protetto. Le classi hanno cinque tipi di visibilità: pubblica, privata, strettamente privata, protetta e pubblicata. Discuteremo la visibilità in dettaglio.

  • Inheritance- Quando una classe viene definita ereditando le funzionalità esistenti di una classe genitore, si dice che sia ereditata. Qui la classe figlia erediterà tutte o poche funzioni membro e variabili di una classe genitore. Gli oggetti possono anche essere ereditati.

  • Parent Class- Una classe ereditata da un'altra classe. Questa è anche chiamata classe base o super classe.

  • Child Class- Una classe che eredita da un'altra classe. Questa è anche chiamata sottoclasse o classe derivata.

  • Polymorphism- Questo è un concetto orientato agli oggetti in cui la stessa funzione può essere utilizzata per scopi diversi. Ad esempio, il nome della funzione rimarrà lo stesso ma potrebbe richiedere un numero diverso di argomenti e può svolgere attività diverse. Le classi Pascal implementano il polimorfismo. Gli oggetti non implementano il polimorfismo.

  • Overloading- È un tipo di polimorfismo in cui alcuni o tutti gli operatori hanno implementazioni diverse a seconda dei tipi dei loro argomenti. Allo stesso modo le funzioni possono anche essere sovraccaricate con implementazioni diverse. Le classi Pascal implementano il sovraccarico, ma gli oggetti no.

  • Data Abstraction - Qualsiasi rappresentazione di dati in cui i dettagli di implementazione sono nascosti (astratti).

  • Encapsulation - Si riferisce a un concetto in cui incapsuliamo tutti i dati e le funzioni membro insieme per formare un oggetto.

  • Constructor - Si riferisce a un tipo speciale di funzione che verrà chiamata automaticamente ogni volta che si verifica la formazione di un oggetto da una classe o da un oggetto.

  • Destructor - Si riferisce a un tipo speciale di funzione che verrà chiamata automaticamente ogni volta che un oggetto o una classe viene eliminata o esce dall'ambito.

Definizione di oggetti Pascal

Un oggetto viene dichiarato utilizzando la dichiarazione del tipo. La forma generale di una dichiarazione di oggetto è la seguente:

type object-identifier = object  
   private
   field1 : field-type;  
   field2 : field-type;  
   ...
   public
   procedure proc1;  
   function f1(): function-type;
   end;  
var objectvar : object-identifier;

Definiamo un oggetto Rectangle che ha due membri di dati di tipo intero: length e width e alcune funzioni membro per manipolare questi membri dati e una procedura per disegnare il rettangolo.

type 
   Rectangle = object  
   private  
      length, width: integer; 
   
   public  
      constructor init;  
      destructor done;  
      
      procedure setlength(l: inteter);  
      function getlength(): integer;  
      
      procedure setwidth(w: integer);  
      function getwidth(): integer;  
      
      procedure draw;
end;
var
   r1: Rectangle;
   pr1: ^Rectangle;

Dopo aver creato i tuoi oggetti, sarai in grado di chiamare le funzioni membro relative a quell'oggetto. Una funzione membro sarà in grado di elaborare la variabile membro solo dell'oggetto correlato.

L'esempio seguente mostra come impostare lunghezze e larghezze per due oggetti rettangolari e disegnarli chiamando le funzioni membro.

r1.setlength(3);
r1.setwidth(7);

writeln(' Draw a rectangle: ', r1.getlength(), ' by ' , r1.getwidth());
r1.draw;
new(pr1);
pr1^.setlength(5);
pr1^.setwidth(4);

writeln(' Draw a rectangle: ', pr1^.getlength(), ' by ' ,pr1^.getwidth());
pr1^.draw;
dispose(pr1);

Di seguito è riportato un esempio completo per mostrare come utilizzare gli oggetti in Pascal:

program exObjects;
type 
   Rectangle = object  
   private  
      length, width: integer; 
   
   public  
      procedure setlength(l: integer);
      function getlength(): integer;  
      
      procedure setwidth(w: integer);  
      function getwidth(): integer;  
      
      procedure draw;
end;
var
   r1: Rectangle;
   pr1: ^Rectangle;

procedure Rectangle.setlength(l: integer);
begin
   length := l;
end;

procedure Rectangle.setwidth(w: integer);
begin
   width :=w;
end;

function Rectangle.getlength(): integer;  
begin
   getlength := length;
end;

function Rectangle.getwidth(): integer;  
begin
   getwidth := width;
end;

procedure Rectangle.draw;
var 
   i, j: integer;
begin
   for i:= 1 to length do
   begin
     for j:= 1 to width do
        write(' * ');
     writeln;
   end;
end;

begin
   r1.setlength(3);
   r1.setwidth(7);
   
   writeln('Draw a rectangle:', r1.getlength(), ' by ' , r1.getwidth());
   r1.draw;
   new(pr1);
   pr1^.setlength(5);
   pr1^.setwidth(4);
   
   writeln('Draw a rectangle:', pr1^.getlength(), ' by ' ,pr1^.getwidth());
   pr1^.draw;
   dispose(pr1);
end.

Quando il codice precedente viene compilato ed eseguito, produce il seguente risultato:

Draw a rectangle: 3 by 7
* * * * * * *
* * * * * * *
* * * * * * *
Draw a rectangle: 5 by 4
* * * *
* * * *
* * * *
* * * *
* * * *

Visibilità dei membri dell'oggetto

La visibilità indica l'accessibilità dei membri dell'oggetto. I membri dell'oggetto Pascal hanno tre tipi di visibilità:

Suor n Visibilità e accessibilità
1

Public

I membri possono essere utilizzati da altre unità esterne all'unità di programma

2

Private

I membri sono accessibili solo nell'unità corrente.

3

Protected

I membri sono disponibili solo per gli oggetti discendenti dall'oggetto padre.

Per impostazione predefinita, i campi e i metodi di un oggetto sono pubblici e vengono esportati all'esterno dell'unità corrente.

Costruttori e distruttori per oggetti Pascal -

Constructorssono metodi di tipo speciale, che vengono chiamati automaticamente ogni volta che viene creato un oggetto. Crei un costruttore in Pascal semplicemente dichiarando un metodo con un costruttore di parole chiave. Convenzionalmente, il nome del metodo è Init, tuttavia, è possibile fornire qualsiasi identificatore valido. Puoi passare tutti gli argomenti che desideri nella funzione di costruzione.

Destructorssono metodi che vengono chiamati durante la distruzione dell'oggetto. I metodi del distruttore distruggono qualsiasi allocazione di memoria creata dai costruttori.

L'esempio seguente fornirà un costruttore e un distruttore per la classe Rectangle che inizializzerà lunghezza e larghezza per il rettangolo al momento della creazione dell'oggetto e lo distruggerà quando esce dall'ambito.

program exObjects;
type 
   Rectangle = object  
   private  
      length, width: integer; 
   public  
      constructor init(l, w: integer);
      destructor done;
      
      procedure setlength(l: integer);
      function getlength(): integer;  
      
      procedure setwidth(w: integer);  
      function getwidth(): integer;  
      
      procedure draw;
end;

var
   r1: Rectangle;
   pr1: ^Rectangle;

constructor Rectangle.init(l, w: integer);
begin
   length := l;
   width := w;
end;

destructor Rectangle.done;
begin
   writeln(' Desctructor Called');
end; 

procedure Rectangle.setlength(l: integer);
begin
   length := l;
end;

procedure Rectangle.setwidth(w: integer);
begin
   width :=w;
end;

function Rectangle.getlength(): integer;  
begin
   getlength := length;
end;

function Rectangle.getwidth(): integer;  
begin
   getwidth := width;
end;

procedure Rectangle.draw;
var 
   i, j: integer;
begin
   for i:= 1 to length do
   begin
      for j:= 1 to width do
         write(' * ');
      writeln;
   end;
end;

begin
   r1.init(3, 7);
   writeln('Draw a rectangle:', r1.getlength(), ' by ' , r1.getwidth());
   r1.draw;
   new(pr1, init(5, 4));
   
   writeln('Draw a rectangle:', pr1^.getlength(), ' by ',pr1^.getwidth());
   pr1^.draw;
   pr1^.init(7, 9);
   
   writeln('Draw a rectangle:', pr1^.getlength(), ' by ' ,pr1^.getwidth());
   pr1^.draw;
   dispose(pr1);
   r1.done;
end.

Quando il codice precedente viene compilato ed eseguito, produce il seguente risultato:

Draw a rectangle: 3 by 7
* * * * * * *
* * * * * * *
* * * * * * *
Draw a rectangle: 5 by 4
* * * *
* * * *
* * * *
* * * *
* * * *
Draw a rectangle: 7 by 9
* * * * * * * * *
* * * * * * * * *
* * * * * * * * *
* * * * * * * * *
* * * * * * * * *
* * * * * * * * *
* * * * * * * * *
Destructor Called

Eredità per oggetti Pascal

Gli oggetti Pascal possono opzionalmente ereditare da un oggetto genitore. Il seguente programma illustra l'ereditarietà in Pascal Objects. Creiamo un altro oggetto denominatoTableTop, che eredita dall'oggetto Rectangle.

program exObjects;
type 
   Rectangle = object  
   private  
      length, width: integer; 
   public  
      procedure setlength(l: integer);  
      function getlength(): integer;  
      procedure setwidth(w: integer);  
      function getwidth(): integer;  
      procedure draw;
end;

TableTop = object (Rectangle)
   private
     material: string;
   public
      function getmaterial(): string;
      procedure setmaterial( m: string);
      procedure displaydetails;
      procedure draw;
end;

var
   tt1: TableTop;

procedure Rectangle.setlength(l: integer);
begin
   length := l;
end;

procedure Rectangle.setwidth(w: integer);
begin
   width :=w;
end;

function Rectangle.getlength(): integer;  
begin
   getlength := length;
end;

function Rectangle.getwidth():integer;
begin
   getwidth := width;
end;

procedure Rectangle.draw;
var 
   i, j: integer;
begin
   for i:= 1 to length do
   begin
      for j:= 1 to width do
         write(' * ');
      writeln;
  end;
end;

function TableTop.getmaterial(): string;
begin
   getmaterial := material;
end;

procedure TableTop.setmaterial( m: string);
begin
   material := m;
end;

procedure TableTop.displaydetails;
begin
   writeln('Table Top: ', self.getlength(), ' by ' , self.getwidth());
   writeln('Material: ', self.getmaterial());
end;

procedure TableTop.draw();
var
   i, j: integer;
begin
   for i:= 1 to length do
   begin
      for j:= 1 to width do
         write(' * ');
   writeln;
   end;
   writeln('Material: ', material);
end;

begin
   tt1.setlength(3);
   tt1.setwidth(7);
   tt1.setmaterial('Wood');
   tt1.displaydetails();
   writeln;
   writeln('Calling the Draw method');
   tt1.draw();
end.

Di seguito sono riportati i punti importanti che dovrebbero essere annotati:

  • L'oggetto Tabletop ha ereditato tutti i membri dell'oggetto Rectangle.

  • C'è anche un metodo di disegno in TableTop . Quando il sorteggio metodo viene chiamato utilizzando un TableTop oggetto, il pareggio di TableTop viene invocato.

  • C'è un'istanza implicita denominata self che si riferisce all'istanza corrente dell'oggetto.

Quando il codice precedente viene compilato ed eseguito, produce il seguente risultato:

Table Top: 3 by 7
Material: Wood

Calling the Draw Method 
* * * * * * *
* * * * * * *
* * * * * * *
Material: Wood