Tyyppijärjestelmä

Ohjelmointikielen tyyppijärjestelmä määrittää, kuinka ohjelmointikieli luokittelee ohjelmassa esiintyvät entiteetit tyyppeihin. Tyyppejä ovat lausekkeet, muuttujat ja niin edelleen. Tyyppijärjestelmä vaikuttaa kuinka kielessä käsitellään tyyppejä ja tyyppien välisiä toimintoja.
Tyyppi tai tietotyyppi on numeeristen arvojen tulkintatapa. Tyyppi voi koostua joukosta sallittuja arvoja (enumeraatio). Tyyppi voi olla komposiittityyppi, joka sisältää useita arvoja (kuten taulukko, luokka ja niin edelleen).
Tyyppijärjestelmä voi olla laajennettava: ohjelmoija voi määrittää uusia tyyppejä kuten luokkia.
Merkitys.
Tietotyypit antavat tulkinnan tietokoneen muistissa oleville bittijonoille. Tavanomaisten tietokoneiden muisti koostuu järjestyksessä olevista biteistä, joiden tulkinta on vapaa. Niinpä sama osa muistin sisältöä voidaan tulkita vaikkapa merkiksi, kokonaisluvuksi, liukuluvuksi tai osoitteeksi toiseen muistipaikkaan. Tyypit kertovat ohjelmille ja ohjelmoijille, kuinka nämä bitit tulkitaan.
Muuttujan tai arvon tyyppi määrittelee, millä tavoin se voi toimia muiden muuttujien tai arvojen kanssa. Tyyppitarkastuksessa varmistutaan siitä, että tyypit toimivat näiden rajoitusten mukaan, eli tarkastetaan osa ohjelman semantiikasta. Tyyppitarkastus voidaan suorittaa ohjelman käännösaikana ("staattinen tyyppitarkastus") tai ajoaikana ("dynaaminen tyyppitarkastus").
Ohjelmointikielissä voidaan antaa lause:
int abc = 42;
.. jossa codice_1 on muuttujan codice_2 "tyyppi" ja "literaali" codice_3 on muuttujaan sijoitettava arvo.
Kääntäjä antaa virheen, jos muuttujaan yritetään sijoittaa jotain mitä tyyppijärjestelmän mukaan siihen ei voida sijoittaa kuten:
vector&lt;int&gt; v;
abc = v; // VIRHE
Tyyppijärjestelmä havaitsee jos tyypillä yritetään tehdä toimintoja, joita sillä ei voida tehdä:
cout « abc + abc; // ok
cout « *abc; // VIRHE
Tyyppijärjestelmä antaa seuraavia merkittäviä hyötyjä:
 "Hello, World" / 3
voidaan tunnistaa virheelliseksi, koska merkkijonon jakaminen kokonaisluvulla ei ole mielekäs operaatio.
Ensimmäisen luokan tyyppejä ovat helposti käytettävät muuttujatyypit kuten codice_1 C++-kielessä. Ensimmäisen luokan tyypeillä:
Eräät kielet tukevat funktioita ensimmäisen luokan tyyppeinä: näitä ovat muun muassa Haskell, Scheme, Python ja Lua.
Yksittäisen rajapinnan tarjoamista erityyppisille entiteeteille kutsutaan polymorfismiksi.
Staattinen vs. dynaaminen tyypitys.
Tyyppijärjestelmä voi olla staattinen tai dynaaminen: staattisessa tyypityksessä tyyppisidos päätetään käännösvaiheessa kun taas dynaamisessa tyypityksessä tyyppi tarkistetaan ja päätetään ajonaikaisesti.
Esimerkiksi C-kielen tyyppijärjestelmä on staattinen, koska muuttujien tyypit on pakko antaa muuttuja- ja funktioesittelyiden yhteydessä. Sen sijaan useimmat tulkattavat (eivät kuitenkaan kaikki) kielet ovat dynaamisesti tyypittäviä kieliä, kuten Perl ja Python. Java käyttää yhdistelmää käännösaikaisia ja ajonaikaisia tarkistuksia.
Esimerkiksi seuraava ohjelmakoodinpätkä on laillista Pythonia:
 def parse_arg(index):
 count, filename = ARGV[0], ARGV[1]
 count = int(count)
 return count, filename
Aluksi codice_5 on tässä merkkijonotyyppinen, koska taulukon codice_6 (komentoriviargumentit) alkiot ovat merkkijonoja. Seuraavalla rivillä codice_5 muunnetaan kokonaislukutyyppiseksi ennen codice_8 -lausetta. Muuttujan codice_5 tyyppi siis vaihtuu ajonaikana, mutta siitä ei aiheudu virhettä.
Dynaaminen tyypitys tarjoaa joustavuutta, mutta se ei ole automaattisesti staattista tyypitystä parempi ratkaisu. Staattisen tyyppijärjestelmän avulla monet virheet voidaan havaita käännösaikana, kun taas dynaamisesti tyypitetyssä kielessä vastaava virhe havaitaan vasta ajon aikana.
Joissakin kielissä tyyppi voidaan päätellä, jolloin se näyttää dynaamiselta mutta on todellisuudessa staattisesti tyypitetty:
var x = 10; // C#
auto x = 10; // C++
// molemmissa vastaa samaa kuin:
int x = 10;
OCaml käyttää "implisiittistä" tyypitystä, joka kuitenkin on staattisesti tyypitetty.
Manifesti vs. implisiittinen tyypitys.
Kielissä, joissa tyyppi määritetään "eksplisiittisesti" käytetään manifestityypitystä ja tyyppiannotaatiota. Esimerkiksi:
double sq47(double n)
 double result = 4.7 * n * n;
 return result;
Muutoin käytössä on implisiittinen tyypitys, jolloin tyyppi voidaan päätellä. Dynaamisesti tyypitetyt kielet käyttävät yleensä implisiittistä tyypistystä.
Esimerkki implisiittisestä tyypityksestä Haskell-kielellä, joka käyttää staattista tyypitystä:
sq47 n = result where
 result = 4.7 * n * n
Joissakin tapauksissa dynaaminen ja implisiittinen voivat näyttää samoilta, mutta käytännössä ovat eri asioita.
Nimellinen vs. rakenteellinen.
Kielet voivat käyttää nimettyä tyyppiä huolimatta sen rakenteesta, jolloin tyyppi tarkistetaan vain sille annetun nimen perusteella. Esimerkiksi ohjelmoijan luomat tyypit:
struct A {
 int h;
 int m;
struct B {
 int h;
 int m;
.. jossa codice_10 ja codice_11 ovat eri tyyppejä.
Nimelliseen tyyppiin on löyhempiä tapauksia, kuten perityn luokan välittäminen sen kantaluokan mukaan.
Rakenteellisessa tyypityksessä (kutsutaan myös "ankkatyypitykseksi") tyyppejä voidaan käsitellä keskenään vaihdettavina mikäli niillä on sama rakenne ja ne tukevat samoja toimintoja.
Esimerkiksi C++-kielellä:
template &lt;typename T, typename U&gt;
T addEm(T a, U b)
 return a + b;
Python-kielellä:
def addEm(a, b):
 return a + b
Go-kielellä:
type Shape interface {
 Area() float64
Latentti tyypitys.
Latentti tyypitys on ohjelmointikielien kuten Schemen tyypitys, jossa yleisesti ottaen et voi ohjelman lähdekoodia lukemalla päätellä mitä tyyppiä tiettyyn muuttujaan tai lausekkeeseen liittyvä data on.
Vahva ja heikko tyypitys.
Vahva ja heikko tyypitys on tyyppijärjestelmän ominaisuus, joka määrittelee miten erityyppisten muuttujien väliset muunnokset käsitellään keskenään. Kieli voi käyttää joko vahvaa tai heikkoa tyypitystä.
Tyyppijärjestelmättömät ohjelmointikielet.
Eräissä ohjelmointikielissä ei ole tyyppijärjestelmää: esimerkkejä ovat BCPL ja B-kielet.
Forth-kieli erottelee kokonaisluvut ja liukuluvut, joten sillä on tyypin käsite, mutta näitä käsitellään eri syntaksilla ja sillä ei ole tyyppitarkistusta.