Programmazione D - Modelli

I modelli sono la base della programmazione generica, che implica la scrittura di codice in modo indipendente da qualsiasi tipo particolare.

Un modello è un progetto o una formula per creare una classe o una funzione generica.

I modelli sono la funzionalità che consente di descrivere il codice come un modello, affinché il compilatore generi automaticamente il codice del programma. Parti del codice sorgente possono essere lasciate al compilatore da compilare fino a quando quella parte non viene effettivamente utilizzata nel programma. Il compilatore inserisce le parti mancanti.

Modello di funzione

Definire una funzione come modello significa lasciare uno o più dei tipi che utilizza come non specificati, per essere dedotti in seguito dal compilatore. I tipi che vengono lasciati non specificati sono definiti nell'elenco dei parametri del modello, che si trova tra il nome della funzione e l'elenco dei parametri della funzione. Per questo motivo, i modelli di funzione hanno due elenchi di parametri:

  • elenco dei parametri del modello
  • lista dei parametri di funzione
import std.stdio; 
 
void print(T)(T value) { 
   writefln("%s", value); 
}
  
void main() { 
   print(42);  
   
   print(1.2);
   
   print("test"); 
}

Se compiliamo ed eseguiamo il codice sopra, questo produrrebbe il seguente risultato:

42 
1.2 
test

Modello di funzione con più parametri di tipo

Possono essere presenti più tipi di parametri. Sono mostrati nel seguente esempio.

import std.stdio;
  
void print(T1, T2)(T1 value1, T2 value2) { 
   writefln(" %s %s", value1, value2); 
}

void main() { 
   print(42, "Test");  
   
   print(1.2, 33); 
}

Se compiliamo ed eseguiamo il codice sopra, questo produrrebbe il seguente risultato:

42 Test 
 1.2 33

Modelli di classe

Così come possiamo definire modelli di funzione, possiamo anche definire modelli di classe. L'esempio seguente definisce la classe Stack e implementa metodi generici per eseguire il push e il pop degli elementi dallo stack.

import std.stdio; 
import std.string; 
 
class Stack(T) { 
   private: 
      T[] elements;  
   public:  
      void push(T element) { 
         elements ~= element; 
      }
      void pop() { 
         --elements.length; 
      } 
      T top() const @property { 
         return elements[$ - 1]; 
      }
      size_t length() const @property { 
         return elements.length; 
      } 
}
  
void main() { 
   auto stack = new Stack!string;
   
   stack.push("Test1"); 
   stack.push("Test2");  
   
   writeln(stack.top); 
   writeln(stack.length); 
   
   stack.pop; 
   writeln(stack.top); 
   writeln(stack.length); 
}

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

Test2 
2 
Test1 
1