Opregnede type

Den aktuelle version af siden er endnu ikke blevet gennemgået af erfarne bidragydere og kan afvige væsentligt fra den version , der blev gennemgået den 19. maj 2014; checks kræver 12 redigeringer .

Enumereret type (forkortet enumeration , eng.  enumeration, enumerated type ) - i programmeringsdatatype , hvis værdisæt er en begrænset liste over identifikatorer.

Beskrivelse og brug

En optalt type er defineret som et sæt af identifikatorer, der fra et sprogsynspunkt spiller samme rolle som regulære navngivne konstanter, men er forbundet med den type. Den klassiske beskrivelse af en opregningstype i Pascal er som følger:

type Cardsuit = ( køller , ruder , hjerter , spar ) ;

Her er Cardsuit-datatypen deklareret, hvis værdier kan være en hvilken som helst af de fire angivne konstanter. En typevariabel Cardsuitkan tage en af ​​værdierne clubs, diamonds, hearts, spades, det er tilladt at sammenligne værdier af opregningstypen for lighed eller ulighed, samt bruge dem i selektionsudsagn (i Pascal - case) som værdier, der identificerer muligheder.

Brugen af ​​opregninger gør det muligt at gøre programmernes kildekoder mere læsbare, da de tillader at erstatte "magiske tal", der koder visse værdier med læsbare navne.

På basis af opregninger på nogle sprog kan der oprettes typesæt . I sådanne tilfælde forstås (og beskrives) et sæt som en uordnet samling af unikke værdier af en enum-type.

En optalt type kan bruges i deklarationer af variable og formelle parametre for funktioner (procedurer, metoder). Værdier af en optalt type kan tildeles de tilsvarende variable og føres gennem parametre for de tilsvarende typer i funktioner. Derudover understøttes altid sammenligning af opregnede værdier for lighed og ulighed. Nogle sprog understøtter også andre sammenligningsoperatorer for værdier af opregnede typer. Resultatet af sammenligning af to opregnede værdier i sådanne tilfælde bestemmes som regel af rækkefølgen af ​​disse værdier i typedeklarationen - den værdi, der forekommer tidligere i typedeklarationen, betragtes som "mindre" end værdien, der sker senere. Nogle gange kan en optalt type eller et område af værdier af en opregnet type også bruges som en indekstype for en matrix. I dette tilfælde er der et element i arrayet for hver værdi i det valgte område, og den faktiske rækkefølge af elementerne svarer til rækkefølgen af ​​værdierne i typeerklæringen.

Implementering

Normalt, under kompilering, er opregningsværdier repræsenteret ved hjælp af heltal. Afhængigt af det specifikke programmeringssprog kan en sådan repræsentation enten være fuldstændig skjult for programmøren eller tilgængelig for ham ved hjælp af visse "løsninger" (f.eks. tvungen konvertering af en enum-typeværdi til en "heltals"-typeværdi), eller endda kontrolleret af programmøren (i sådanne tilfælde har programmøren mulighed for eksplicit at angive, hvilke tal alle eller nogle værdier af enum-typen vil blive kodet med. Alle muligheder har deres positive og negative sider. På den ene side fratager evnen til at bruge de numeriske værdier af konstanterne, der udgør opregningstypen, især når den misbruges, brugen af ​​disse typer og skaber fare for fejl (når der bruges numeriske værdier for som der ikke er tilsvarende konstanter i typen). På den anden side giver eksplicit værdistyring nogle ekstra funktioner. For eksempel tillader det at bruge enum-typer, når du organiserer en grænseflade med moduler skrevet på andre sprog, hvis de bruger eller returnerer heltalskodede værdier fra et foruddefineret sæt.

En anden mulighed, som opregnede typer giver på sprogimplementeringsniveauet, er hukommelsesbesparelse. Med en lille mængde enum-type er et par bit nok til at gemme en værdi af denne type (ovenstående type Cardsuitkræver kun to bit pr. værdi, mens et standard heltal på de fleste brugte arkitekturer tager 32 bit - 16 gange mere), og compiler kan bruge dette faktum til at komprimere lagring af data i hukommelsen. Dette kan især være vigtigt, hvis flere værdier af enum-typer er gemt i en enkelt post - komprimering af poster ved behandling af et stort antal af dem kan frigøre en masse hukommelse. Compilere implementerer normalt ikke denne funktion, i hvert fald ikke i nyere tid, hvor computerhukommelse er blevet meget billigere.

Kritik

Opregningstypen er traditionel for udviklede programmeringssprog, bruges ret meget og tages ofte for givet. Denne type er dog heller ikke uden kritik fra teoretikere og praktikere af programmering. Så når man udviklede Oberon -programmeringssproget, blev opregnede typer inkluderet i listen over funktioner, der blev fjernet fra sproget. Niklaus Wirth , designeren af ​​sproget, citerede følgende grunde:

  • "i et stigende antal programmer fører den uigennemtænkte brug af enums ... til en befolkningseksplosion blandt typer, som igen fører ikke til klarhed i programmerne, men til ordlyd" [1] ;
  • når en enum-type eksporteres af et modul (det vil sige, at den bliver en del af en grænseflade ), overtrædes den generelle regel - type eksport-kommandoen eksporterer samtidig alle dens elementer, mens type eksport for alle andre typer skjuler dens interne struktur;
  • Fra et programlæsbarhedssynspunkt er der intet, der forhindrer dig i kun at bruge en gruppe af co-definerede navngivne konstanter i stedet for en opregnet type, især i nærvær af sprogmekanismer såsom moduler eller klasser.

På den anden side, f.eks. i Java , som oprindeligt ikke indeholdt en opregnet type, blev denne type efterfølgende introduceret af ikke kun bekvemmelighedsgrunde, men også af pålidelighed: Problemet med at bruge grupper af navngivne konstanter i stedet for opregninger er, at der er ingen kontrol fra compileren med hensyn til unikheden af ​​værdikonstanter, såvel som muligheden for tilfældigt at tildele værdier til variabler, der ikke svarer til nogen af ​​disse konstanter.

Beskrivelse af enums på forskellige sprog

Ada

I Ada-sproget angives opregninger ved hjælp af et nøgleord isefterfulgt af en kommasepareret liste med værdier:

type Cardsuit er ( køller , ruder , hjerter , spar );

C og sprog med C-lignende syntaks

Den originale K&R- dialekt af C havde ikke opregnede typer, men de blev tilføjet i ANSI C -standarden .

enum cardsuit { KLUBER , DIAMANTER , HJERTER , SPADER };

Dynamiske, svagt indtastede sprog med C-lignende syntaks (såsom perl eller JavaScript ) har generelt ikke enums.

C++

C++ enums arver direkte adfærden af ​​C enums, bortset fra at den optalte type i C++ er en reel type, og nøgleordet enumbruges kun, når en sådan type erklæres. Hvis der ved behandling af en parameter, der er en opregning, en værdi fra optællingen ikke behandles (for eksempel blev et af opregningselementerne glemt at blive behandlet i konstruktionen switch), så kan compileren udstede en advarsel om den glemte værdi. [2]

C++11 giver en anden, typesikker enum-type, der ikke implicit kan konverteres til en integraltype. Dette er defineret af udtrykket "enum-klasse". For eksempel:

enum klasse Farve { Rød , Grøn , Blå };

En basistype er en implementering af en bestemt integraltype, der er stor nok til at indeholde alle de anførte værdier (det behøver ikke at være den mindst mulige type!). I C++ kan du angive basistypen direkte. Dette tillader "fremsende erklæringer" af enums:

enum klasse Farve : lang { Rød , Grøn , Blå }; // skal matche størrelsen og layoutet af hukommelsestypen "lang" enum -klasse Shapes : char ; // foreløbig erklæring. Hvis der senere defineres værdier, der ikke passer i 'char', er dette en fejl. C# enum Cardsuit { kløver , ruder , spar , hjerter } Java

I den oprindelige Java var der ingen optællinger; i stedet blev det foreslået at bruge klasser med statiske konstanter. Da version 5 (1.5) opregninger er blevet introduceret i sproget, er de en fuldgyldig klasse, hvor du kan tilføje et vilkårligt antal felter og metoder. Enums blev indført for at forbedre typesikkerhedskontrol. [3]

enum Cardsuit { kløver , ruder , spar , hjerter } Kotlin enum klasse Retning { NORD , SYD , VEST , ØST }

Haskell

I nogle programmeringssprog (f.eks. Haskell) kan optællinger emuleres ved hjælp af algebraiske typer . For eksempel er en boolsk type, der indeholder to identifikatorer til at repræsentere sandhedsværdier, kodet som dette:

data Bool = Falsk | Rigtigt

Nim

type enumType = enum one , two , three var a : enumType = tre var b = to ekko a > b

Vala

//Regulær enum enum Farver { GRØN = 1 , BLÅ , RØD } //Flag enum [ Flag ] enum Borders { VENSTRE , HØJRE , TOP , BUND } void draw_borders ( Borders selected_borders ) { // svarende til: if ((Borders.LEFT & selected_borders) > 0) if ( Borders . LEFT in selected_borders ) { } }

soliditet

pragma soliditet ^ 0.4.4 ; kontrakt SimpleEnum { enum SomeData { DEFAULT , ONE , TWO } SomeData someData ; function SimpleEnum (){ someData = SomeData . STANDARD ; } function setValues ​​​​( uint _value ) { require ( uint ( SomeData . TWO ) >= _value ); someData = SomeData ( _value ); } funktion getValue () konstant returnerer ( uint ){ returnerer uint ( someData ); } }


Noter

  1. N. Wirth. Fra Modula til Oberon . Hentet 17. april 2008. Arkiveret fra originalen 19. september 2011.
  2. Optællinger i C++ (c++ enum-typer) . Hentet 20. april 2009. Arkiveret fra originalen 16. april 2009.
  3. Enums . Hentet 13. februar 2008. Arkiveret fra originalen 27. februar 2008.