Luettelotyyppi

Kokeneet kirjoittajat eivät ole vielä tarkistaneet sivun nykyistä versiota, ja se voi poiketa merkittävästi 19. toukokuuta 2014 tarkistetusta versiosta . tarkastukset vaativat 12 muokkausta .

Luettelotyyppi (lyhennetty luettelointi , eng.  enumeration, enumerated type ) - ohjelmoinnin tietotyyppi , jonka arvojoukko on rajoitettu tunnisteluettelo.

Kuvaus ja käyttö

Luettelotyyppi määritellään joukoksi tunnisteita, joilla on kielen näkökulmasta sama rooli kuin tavalliset nimetyt vakiot, mutta jotka liittyvät kyseiseen tyyppiin. Klassinen kuvaus Pascalin luettelotyypistä on seuraava:

tyyppi Cardsuit = ( mailat , timantit , sydämet , pata ) ;

Tässä ilmoitetaan Cardsuit-tietotyyppi, jonka arvot voivat olla mikä tahansa neljästä luetellusta vakiosta. Tyyppimuuttuja Cardsuitvoi ottaa yhden arvoista clubs, diamonds, hearts, spades, se on sallittua vertailla laskentatyypin arvoja yhtäläisyydelle tai epätasa-arvolle sekä käyttää niitä valintalausekkeissa (Pascal - case) arvoina, jotka tunnistavat vaihtoehdot.

Luetteloiden käyttö mahdollistaa ohjelmien lähdekoodien luettavuuden, koska ne mahdollistavat tiettyjä arvoja koodaavien "maagisten numeroiden" korvaamisen luettavissa olevilla nimillä.

Joidenkin kielten luetteloiden perusteella voidaan luoda tyyppijoukkoja . Tällaisissa tapauksissa joukko ymmärretään (ja kuvataan) enum-tyyppisten ainutlaatuisten arvojen järjestämättömänä kokoelmana.

Luettelotyyppiä voidaan käyttää muuttujien ja funktioiden muodollisten parametrien (proseduurit, menetelmät) määrittelyssä. Luettelotyyppiset arvot voidaan määrittää vastaaville muuttujille ja kuljettaa niitä vastaavien tyyppien parametrien läpi funktioissa. Lisäksi tasa-arvon ja eriarvoisuuden lueteltujen arvojen vertailua tuetaan aina. Jotkut kielet tukevat myös muita vertailuoperaattoreita lueteltujen tyyppien arvoille. Kahden luetun arvon vertailun tulos tällaisissa tapauksissa määräytyy pääsääntöisesti näiden arvojen järjestyksen mukaan tyyppiselvityksessä - arvoa, joka esiintyy aikaisemmin tyyppiilmoituksessa, pidetään "pienempänä" kuin arvo, tapahtuu myöhemmin. Joskus taulukon indeksityyppinä voidaan käyttää myös lueteltua tyyppiä tai jotakin lueteltua tyyppiä olevaa arvoaluetta. Tässä tapauksessa taulukossa on yksi elementti jokaiselle valitun alueen arvolle, ja elementtien todellinen järjestys vastaa tyyppiilmoituksen arvojen järjestystä.

Toteutus

Normaalisti kokoamisen aikana luettelointiarvot esitetään kokonaislukuina. Tietystä ohjelmointikielestä riippuen tällainen esitys voi olla joko kokonaan piilotettu ohjelmoijalta tai hänen käytettävissään käyttämällä tiettyjä "kiertotapoja" (esimerkiksi enum-tyypin arvon pakotettu muuntaminen "kokonaisluku"-tyyppiseksi arvoksi) tai jopa ohjelmoijan ohjaama (tällaisissa tapauksissa ohjelmoijalla on mahdollisuus nimenomaisesti määrittää, millä numeroilla kaikki tai jotkin enum-tyypin arvot koodataan. Kaikilla vaihtoehdoilla on hyvät ja huonot puolensa. Toisaalta kyky käyttää laskentatyypin muodostavien vakioiden numeerisia arvoja, varsinkin kun sitä käytetään väärin, estää näiden tyyppien käytön ja aiheuttaa virhevaaran (käytettäessä numeerisia arvoja joita tyypissä ei ole vastaavia vakioita). Toisaalta eksplisiittinen arvonhallinta tarjoaa joitain lisäominaisuuksia. Se mahdollistaa esimerkiksi enum-tyyppien käytön järjestettäessä käyttöliittymää muilla kielillä kirjoitetuilla moduuleilla, jos ne käyttävät tai palauttavat kokonaislukukoodattuja arvoja jostain ennalta määritetystä joukosta.

Toinen mahdollisuus, jonka luetellut tyypit tarjoavat kielen toteutustasolla, on muistin säästäminen. Pienellä määrällä enum-tyyppiä muutama bitti riittää tallentamaan tämän tyyppisen arvon (edellä oleva tyyppi Cardsuitvaatii vain kaksi bittiä arvoa kohden, kun taas tavallinen kokonaisluku useimmissa käytetyissä arkkitehtuureissa vie 32 bittiä - 16 kertaa enemmän), ja kääntäjä voi käyttää tätä tosiasiaa tiivistämään tietojen tallentamista muistiin. Tämä voi olla erityisen tärkeää, jos yhteen tietueeseen on tallennettu useita enum-tyyppien arvoja - tietueiden tiivistäminen niitä suuria määriä käsiteltäessä voi vapauttaa paljon muistia. Kääntäjät eivät yleensä ota käyttöön tätä ominaisuutta, ainakaan viime aikoina, kun tietokoneen muisti on tullut paljon halvemmaksi.

Kritiikki

Luettelotyyppi on perinteinen kehittyneille ohjelmointikielille, sitä käytetään melko laajalti ja sitä pidetään usein itsestäänselvyytenä. Tämä tyyppi ei kuitenkaan ole vailla kritiikkiä ohjelmoinnin teoreetikoilta ja harjoittajilta. Joten Oberon -ohjelmointikieltä kehitettäessä luetellut tyypit sisällytettiin kielestä poistettujen ominaisuuksien luetteloon. Kielen suunnittelija Niklaus Wirth mainitsi seuraavat syyt:

  • "Yhä useammissa ohjelmissa enumien väärin suunniteltu käyttö ... johtaa väestöräjähdysmäiseen räjähdysmäiseen tyyppeihin, mikä puolestaan ​​​​ei johda ohjelmien selkeyteen, vaan monisanaisuuksiin" [1] ;
  • kun moduuli vie enum-tyypin ( eli siitä tulee osa käyttöliittymää ), yleissääntöä rikotaan - type export -komento vie samanaikaisesti kaikki elementit, kun taas kaikkien muiden tyyppien tapauksessa type export piilottaa sisäisen rakenteensa;
  • Ohjelman luettavuuden näkökulmasta mikään ei estä sinua käyttämästä vain yhteismääriteltyjen nimettyjen vakioiden ryhmää luetteloidun tyypin sijaan, varsinkin kun on olemassa kielimekanismeja, kuten moduuleja tai luokkia.

Toisaalta esimerkiksi Javassa , joka alun perin ei sisältänyt lueteltua tyyppiä, tämä tyyppi otettiin myöhemmin käyttöön paitsi mukavuussyistä myös luotettavuudesta: nimettyjen vakioryhmien käytön ongelmana numerointien sijaan on se, että kääntäjä ei voi hallita arvovakioiden yksilöllisyyttä, samoin kuin mahdollisuutta antaa satunnaisesti arvoja muuttujille, jotka eivät vastaa mitään näistä vakioista.

Kuvaus enumeista eri kielillä

Ada

Ada-kielessä luettelot määritetään avainsanalla is, jota seuraa pilkuilla eroteltu arvoluettelo:

tyyppi Cardsuit on ( mailat , timantit , sydämet , pata );

C ja kielet C:n kaltaisella syntaksilla

C :n alkuperäisellä K&R -murteella ei ollut lueteltuja tyyppejä, mutta ne lisättiin ANSI C -standardiin .

enum korttipuku { KLUBIT , Timantteja , SYDÄMET , PATA };

Dynaamisissa, heikosti kirjoitetuissa kielissä, joissa on C-tyyppinen syntaksi (kuten perl tai JavaScript ), ei yleensä ole enumeita.

C++

C++-luettelot perivät suoraan C-luetteloiden käyttäytymisen, paitsi että C++:n lueteltu tyyppi on todellinen tyyppi ja avainsanaa enumkäytetään vain sellaisen tyypin määrittämisessä. Jos listauksena olevaa parametria käsiteltäessä ei käsitellä mitään luettelon arvoa (esimerkiksi yksi luettelointielementeistä on unohdettu käsitellä konstruktiossa switch), kääntäjä voi antaa varoituksen unohdetusta arvosta. [2]

C++11 tarjoaa toisen, tyyppiturvallisen enum-tyypin, joka ei ole implisiittisesti muunnettavissa kiinteäksi tyypiksi. Tämä määritellään ilmauksella "enum class". Esimerkiksi:

enum class Väri { Punainen , Vihreä , Sininen };

Perustyyppi on tietyn integraalityypin toteutus, joka on riittävän suuri sisältämään kaikki luetellut arvot (sen ei tarvitse olla pienin mahdollinen tyyppi!). C++:ssa voit määrittää perustyypin suoraan. Tämä mahdollistaa enumien "edellyttämisen":

enum class Väri : pitkä { Punainen , Vihreä , Sininen }; // on vastattava muistityypin "long" kokoa ja asettelua enum class Muodot : char ; // alustava ilmoitus. Jos myöhemmin määritetään arvoja, jotka eivät mahdu 'char' -kohtaan, tämä on virhe. C# enum Cardsuit { Clubs , Diamonds , Spades , Hearts } Java

Alkuperäisessä Javassa ei ollut enumeita, vaan sen sijaan ehdotettiin luokkien käyttöä staattisilla vakioilla. Koska versio 5 (1.5) luettelointi on otettu kieleen, ne ovat täysi luokka, johon voit lisätä mielivaltaisen määrän kenttiä ja menetelmiä. Enummit otettiin käyttöön tyyppiturvallisuuden parantamiseksi. [3]

enum Cardsuit { Clubs , Diamonds , Spades , Hearts } Kotlin enum class Suunta { POHJOIS , ETELÄ , LÄNSI , ITÄ }

Haskell

Joissakin ohjelmointikielissä (esim. Haskell) luetteloita voidaan emuloida käyttämällä algebrallisia tyyppejä . Esimerkiksi Boolen tyyppi, joka sisältää kaksi tunnistetta totuusarvojen esittämiseksi, on koodattu seuraavasti:

tiedot Bool = False | Totta

Nim

tyyppi enumType = enum yksi , kaksi , kolme var a : enumType = kolme var b = kaksi kaikua a > b

Vala

//Säännöllinen enum enum Värit { VIHREÄ = 1 , SININEN , PUNAINEN } //Liput enum [ Liput ] enum Reunat { LEFT , RIGHT , YLÄ , ALA } void draw_borders ( Borders selected_borders ) { // vastaa: if ((Borders.LEFT & selected_borders) > 0) if ( Borders . LEFT in selected_borders ) { } }

solidity

pragma kiinteys ^ 0,4,4 ; sopimus SimpleEnum { enum SomeData { OLETUS , ONE , TWO } SomeData someData ; function SimpleEnum (){ someData = SomeData . OLETUS ; } function setValues ( uint _arvo ){ vaatia ( uint ( SomeData . TWO ) >= _arvo ); someData = SomeData ( _value ); } function getValue () vakio palauttaa ( uint ){ return uint ( someData ); } }


Muistiinpanot

  1. N. Wirth. Modulasta Oberoniin . Haettu 17. huhtikuuta 2008. Arkistoitu alkuperäisestä 19. syyskuuta 2011.
  2. Luettelot C++:ssa (c++ enum-tyypit) . Haettu 20. huhtikuuta 2009. Arkistoitu alkuperäisestä 16. huhtikuuta 2009.
  3. Enums . Haettu 13. helmikuuta 2008. Arkistoitu alkuperäisestä 27. helmikuuta 2008.