Felsorolt típus
A számítógépes programozásban egy felsorolt típus (más néven enumeration, enum, vagy factor az R programozási nyelvben, feltétel-név a COBOL programozási nyelvben, status variable a JOVIAL programozási nyelvben, ordinal a PL/I programozási nyelvben és kategorikus változó a statisztikában) egy adattípus[a], amely elnevezett értékek halmazából áll, amelyeket a típus elemeinek (elements), tagjainak (members), felsorolásainak (enumeral) vagy felsorolóinak enumerators) neveznek. A felsorolt nevek általában azonosítók, amelyek konstansként viselkednek a nyelvben. Egy felsorolt típus tekinthető az egységtípusok degenerált, címkézett uniójának.[1] Egy felsorolt típusként deklarált változóhoz bármelyik felsoroló értéke rendelhető. Más szóval, egy felsorolt típusnak olyan értékei vannak, amelyek egymástól különböznek, és amelyek összehasonlíthatók és hozzárendelhetők, de a programozó általában nem[b] határozza meg, hogy a számítógép memóriájában bármilyen konkrét reprezentációval rendelkezzenek; a fordítóprogramok és interpreterek tetszőlegesen ábrázolhatják ezeket.
Leírás
[szerkesztés]Például egy pakli kártya négy színe lehet négy felsoroló, úgynevezett Treff, Káró, Kőr és Pikk, amelyek egy felsorolt típushoz, a színhez tartoznak. Ha egy V változót szín adattípussal deklarálunk, akkor a négy érték bármelyikét hozzárendelhetjük.
Bár a felsorolók általában különbözőek, egyes nyelvek lehetővé teszik, hogy ugyanazon felsoroló kétszer szerepeljen a típusdeklarációban. A felsorolók nevének nem kell szemantikailag teljesnek vagy bármilyen értelemben kompatibilisnek lennie. Például egy color nevű felsorolt típus definiálható úgy, hogy a Red, Green, Zebra, Missing és Bacon felsorolókból álljon. Egyes nyelvekben a felsorolt típus deklarációja szándékosan meghatározza a tagjainak sorrendjét is (Magas, Közepes és Alacsony prioritás); másokban a felsorolók rendezetlenek (angol, francia, német és spanyol támogatott nyelvek); megint másokban pedig implicit sorrend adódik abból, hogy a fordító konkrétan egész számként reprezentálja a felsorolókat.
Néhány felsoroló típus beépíthető a nyelvbe. A Boole-típus például gyakran a False és True értékek előre definiált felsorolása. Egyetlen értékből álló egységtípus is definiálható a null érték ábrázolására. Számos nyelv lehetővé teszi a felhasználók számára új felsorolt típusok definiálását.
A felsorolt típusú értékeket és változókat általában valamilyen egész típusú reprezentációval valósítják meg. Egyes programozási nyelvek, különösen a rendszerprogramozási nyelvek, lehetővé teszik a felhasználó számára, hogy meghatározza az egyes felsorolókhoz használandó bitkombinációt, ami hasznos lehet a felsorolóhalmazok fix hosszúságú bitláncokként való hatékony ábrázolásához. A típuselméletben a felsorolt típusokat gyakran egységtípusok címkézett unióinak[1] tekintik. Mivel az ilyen típusok alakúak, természetes számokként is felírhatók.
Indoklás
[szerkesztés]Néhány korai programozási nyelv eredetileg nem rendelkezett felsorolt típusokkal. Ha egy programozó azt szerette volna, ha egy változó, például a myColor, a red értéket kapja, akkor a red változót deklarálták, és tetszőleges értéket rendeltek hozzá, általában egy egész konstanst. A red változóhoz ezután a myColor értéket rendelték hozzá. Más technikák tetszőleges értékeket rendeltek a felsorolók nevét tartalmazó karakterláncokhoz.
Ezeket a tetszőleges értékeket néha mágikus számoknak (magic number) nevezték, mivel gyakran nem volt magyarázat arra, hogyan nyerték ki a számokat, vagy hogy a tényleges értékeik jelentősek-e. A mágikus szám egy adott fogalmat azonosít, de további ismeretek nélkül a jelentése nem egyértelmű, ezért a használata megnehezítheti a forráskód megértését és karbantartását mások számára.
A felsorolt típusok ezzel szemben öndokumentálóbbá teszik a kódot. A nyelvtől függően a fordító automatikusan alapértelmezett értékeket rendelhet a felsorolókhoz, ezáltal elrejtve a felesleges részleteket a programozó elől. Ezek az értékek esetleg nem is láthatók a programozó számára (lásd: információ elrejtése). A felsorolt típusok megakadályozhatják, hogy a programozó logikátlan kódot írjon, például matematikai műveleteket hajtson végre a felsorolók értékeivel. Ha egy felsorolóhoz rendelt változó értékét ki kellene nyomtatni, egyes programozási nyelvek a felsoroló nevét is kinyomtathatnák a mögöttes numerikus érték helyett. További előny, hogy a felsorolt típusok lehetővé teszik a fordítók számára a szemantikai helyesség érvényesítését. Például: a myColor = TRIANGLE tiltható, míg a myColor = RED elfogadott, még akkor is, ha a TRIANGLE és a RED is belsőleg 1-es értékkel van reprezentálva.
Fogalmilag egy felsorolt típus hasonló a névleges értékek[2] (numerikus kódok) listájához, mivel a típus minden lehetséges értékéhez egy egyedi természetes szám tartozik. Egy adott felsorolt típus tehát ennek az elképzelésnek a konkrét megvalósítása. Amikor a sorrend értelmes és/vagy összehasonlításra szolgál, akkor egy felsorolt típus ordinális típussá válik.
Megállapodások
[szerkesztés]A programozási nyelveknek általában saját, gyakran több programozási stílusuk és elnevezési konvenciójuk van. A felsoroláshoz rendelt változó általában egyes számú főnév, és gyakran PascalCase vagy nagybetűs konvenciót követ, míg a kisbetűk és más konvenciók ritkábban fordulnak elő.
Szintaxis több programozási nyelven
[szerkesztés]ALGOL 60 alapú nyelvek
[szerkesztés]Míg az ALGOL 60-nak magának nincs felsorolási típusa, számos belőle származó nyelvnek van. Különösen a Pascal volt erős hatással az Ada tervezésére.
Pascal
[szerkesztés]Pascalban egy felsorolt típus implicit módon deklarálható az értékek zárójeles listában való felsorolásával:
var
suit: (clubs, diamonds, hearts, spades);
A deklaráció gyakran egy típusszinonima-deklarációban jelenik meg, így több változóhoz is használható:
type
cardsuit = (clubs, diamonds, hearts, spades);
card = record
suit: cardsuit;
value: 1 .. 13;
end;
var
hand: array [ 1 .. 13 ] of card;
trump: cardsuit;
A felsorolási értékek megadásának sorrendje számít. Egy felsorolt típus egy ordinális típus, és a pred és succ függvények a felsorolás előző vagy következő értékét adják meg, az ord pedig a felsorolási értékeket egész számokká alakíthatja. A standard Pascal azonban nem kínál konverziót aritmetikai típusokról felsorolásokra. A kiterjesztett Pascal ezt a funkciót egy kiterjesztett succ függvényen keresztül kínálja. Néhány más Pascal dialektus típusátalakításokon keresztül teszi lehetővé. A Pascal néhány modern leszármazottja, mint például a Modula-3, egy speciális konverziós szintaxist biztosít egy VAL nevű metódus használatával; a Modula-3 a BOOLEAN és CHAR típusokat is speciális előre definiált felsorolt típusokként kezeli, és az ORD és VAL típusokat használja a szabványos ASCII dekódoláshoz és kódoláshoz.
A Pascal stílusú nyelvek lehetővé teszik a felsorolás tömbindexként való használatát is:
var
suitcount: array [cardsuit] of integer;
Ada
[szerkesztés]Az Adában a felsorolt típusok definíciója hasonló a Pascalhoz, az "=" karaktereket "is"-re cserélve:
type Cardsuit is (clubs, diamonds, hearts, spades);
A Pred, Succ, Val és Pos mellett az Ada támogatja az egyszerű karakterlánc-konverziókat Image and Value segítségével is.
A C stílusú nyelvekhez hasonlóan az Ada lehetővé teszi a felsorolás belső reprezentációjának megadását:
for Cardsuit use
(clubs => 1, diamonds => 2, hearts => 4, spades => 8);
Az Ada lehetővé teszi a felsorolás bitjeinek számának egyértelmű megadását is, ellentétben a C stílusú nyelvekkel, amelyek inkonzisztens támogatással rendelkeznek, ami gyakran finom fordítási hibákhoz[3] vezet. Például:
for Cardsuit'Size use 4; -- 4 bits
Ezenkívül a felsorolások használhatók tömbök indexeként, mint például a Pascalban, de a felsorolásokhoz attribútumok vannak definiálva.
Shuffle : constant array(Cardsuit) of Cardsuit :=
(Clubs => Cardsuit'Succ(Clubs), -- see attributes of enumerations 'First, 'Last, 'Succ, 'Pred
Diamonds => Hearts, --an explicit value
Hearts => Cardsuit'Last, --first enumeration value of type Cardsuit e.g., clubs
Spades => Cardsuit'First --last enumeration value of type Cardsuit e.g., spades
);
A Modula-3-hoz hasonlóan az Ada a Boolean és a Character típusokat speciális, előre definiált (a "Standard" csomagban) felsorolt típusokként kezeli. A Modula-3-mal ellentétben saját karaktertípusokat is definiálhatunk:
type Cards is ('7', '8', '9', 'X', 'J', 'Q', 'K', 'A');
PL/I
[szerkesztés]Sem az eredeti PL/I, sem az ANSI X3.53–1976 nem tartalmaz felsorolásokat, de az IBM Enterprise PL/I[4] ordinális típusokkal rendelkezik.
Egy ordinális változó nem használható közvetlenül alsó indexként vagy DO TO korlátként. Azonban
- A first és last típusfüggvények, a beépített binaryvalue, ordinalpred és ordinalsucc függvények pedig közvetve teszik ezt lehetővé.
- A DO UOTHRU és a DO DOWNTO sorszámok támogatása
define ordinal foo (green,with,envy);
declare ix ordinal foo,
bar(first(:foo:):last(:foo:)) fixed bin;
do i = first(:foo:) to last(:foo:);
bar(i)=13;
end;
do ix=first(:foo:) repeat ordinalsucc(ix) until (ix=first(:foo:)) /* stop on wrap around. */;
i = binaryvalue(ix);
display (bar(i) || ' at ' || ix);
end;
C és szintaktikailag hasonló nyelvek
[szerkesztés]C
[szerkesztés]A C programozási nyelv eredeti K&R dialektusában nem voltak felsorolt típusok.[5] A C-ben a felsorolásokat explicit definíciók hozzák létre (az enum kulcsszó önmagában nem okoz tárhelyfoglalást), amelyek az enum kulcsszót használják, és a struct és union definíciókra emlékeztetnek:
typedef enum {
CLUBS,
DIAMONDS,
HEARTS,
SPADES
} CardSuit;
typedef struct {
CardSuit suit;
short int value;
} Card;
Card hand[13];
CardSuit trump;
A C nyelv közvetlenül a programozó számára teszi elérhetővé a felsorolási értékek egész számként való ábrázolását. Az egész számok és az felsorolási értékek szabadon keverhetők, és az felsorolási értékeken végzett minden aritmetikai művelet megengedett. Az is lehetséges, hogy egy felsorolási változó olyan egész számot tartalmazzon, amely nem képviseli a felsorolási értékek egyikét sem. Valójában a nyelvi definíció szerint a fenti kód a Clubs, Diamonds, Hearts és Spades-t int típusú konstansokként definiálja, amelyek csak akkor (csendben) alakulnak át enum CardSuit felsorolássá, ha egy ilyen típusú változóban vannak tárolva.
A C nyelv lehetővé teszi a programozó számára, hogy explicit módon, típus nélkül is kiválassza a felsorolási állandók értékeit. Például,
enum CardSuit {
CLUBS = 1,
DIAMONDS = 2,
HEARTS = 4,
SPADES = 8
};
használható egy olyan típus definiálására, amely lehetővé teszi a matematikai színű halmazok felsorolt enum CardSuit-ként való ábrázolását bitenkénti logikai műveletekkel.
A C23 óta a felsorolás mögöttes típusát a programozó adhatja meg, ugyanazzal a szintaxissal, mint a C++.[6] Ez lehetővé teszi a programozók számára, hogy optimalizált felsorolásokat készítsenek egy olcsóbb mögöttes típus kiválasztásával.
enum CardSuit : char {
CLUBS = 1,
DIAMONDS = 2,
HEARTS = 4,
SPADES = 8
};
A C nyelvben az enum-ok nincsenek hatókörbe korlátozva vagy minősítve, mivel a C-ből hiányoznak a névtér-funkciók. A constexpr kulcsszó C23-ban való bevezetése előtt az enum-okat gyakran használták fordítási idejű állandók deklarálására a C preprocesszor használata nélkül.
C#
[szerkesztés]A C# programozási nyelvben a felsorolt típusok megőrzik a C felsorolásainak „kis egész” szemantikáját. Néhány aritmetikai művelet nincs definiálva az felsorolásokhoz, de egy enumerálási érték explicit módon konvertálható egész számmá és vissza, és egy felsorolt típusú változó olyan értékeket tartalmazhat, amelyeket az felsorolási definíció nem deklarált. Például, ha
enum CardSuit
{
Clubs,
Diamonds,
Spades,
Hearts
}
A CardSuit.Diamonds + 1 és a CardSuit.Hearts - CardSuit.Clubs kifejezések közvetlenül megengedettek (mert lehet értelmes végiglépkedni az értékek sorozatán, vagy megkérdezni, hogy hány lépés van két érték között), de a CardSuit.Hearts * CardSuit.Spades kevésbé értelmesnek tekinthető, és csak akkor engedélyezett, ha az értékeket először egész számokká alakítjuk.
A C# a C-hez hasonló tulajdonsággal rendelkezik, lehetővé téve konkrét egész értékek definiálását a felsorolásokhoz. Ezáltal bináris műveletek hajthatók végre a felsorolásokon, így a felsorolási értékeket jelzők halmazaként lehet kezelni. Ezek a jelzők bináris műveletekkel vagy az enum típus beépített 'HasFlag' metódusával tesztelhetők.[7]
A felsorolás-definíció neveket ad a kiválasztott egész értékekhez, és szintaktikailag egyszerű (syntactic sugar[8]), mivel egy felsorolásváltozóhoz más egész értékeket is hozzá lehet rendelni, amelyek nem tartoznak az felsorolásdefiníció hatókörébe.[9][10][11]
C++
[szerkesztés]A C++-ban vannak olyan felsorolástípusok, amelyek közvetlenül a C-ből öröklődnek, és többnyire hasonlóan működnek, azzal a különbséggel, hogy a felsorolás egy valódi típus a C++-ban, ami további fordítási idejű ellenőrzést biztosít. Továbbá (a struktúrákhoz hasonlóan) a C++ enum kulcsszó egy typedef-fel van kombinálva, így a típusra enum MyEnum helyett egyszerűen MyEnum-ként lehet hivatkozni. Ez C-ben egy typedef használatával szimulálható: typedef enum { VALUE_1, VALUE_2 } MyEnum;
A C++11 egy második típusú felsorolást is biztosít, amelyet hatókörön belüli felsorolásnak nevezünk (scoped enumeration). Ezek típusbiztosak: a felsorolók nem alakulnak át implicit módon egész típussá. Többek között ez lehetővé teszi az I/O folyamat definiálását a felsorolástípushoz. A hatókörön belüli felsorolások egy másik jellemzője, hogy a felsorolókat az enumeráció nevével kell minősíteni, így a használathoz a felsorolás nevével kell előtagot hozzáadni (pl. Color::RED az első felsorolóhoz az alábbi példában), kivéve, ha a (C++20-ban bevezetett) using enum deklarációval a felsorolókat az aktuális hatókörbe vonták be. A hatókörön belüli felsorolást az enum class (vagy enum struct) kifejezés határozza meg. Például:
// C-style unscoped enum
enum CardSuit {
CLUBS,
DIAMONDS,
SPADES,
HEARTS
};
// C++11-style scoped enum
enum class Color {
RED,
GREEN,
BLUE
};
int main(int argc, char* argv[]) {
Color c = Color::RED;
// Unscoped C-style enum
CardSuit card1 = Clubs; // Can be unscoped
CardSuit card2 = CardSuit::SPADES; // Usually declared scoped however
}
Egy felsorolás alapjául szolgáló mögöttes típus (underlying type) egy implementáció által definiált szerves típus, amely elég nagy ahhoz, hogy az összes felsorolt értéket tartalmazza; nem kell a lehető legkisebb típusnak lennie. Az alapjául szolgáló típus közvetlenül megadható, ami lehetővé teszi a felsorolások „előre deklarálását” (forward declaration):
// illeszkednie kell a 'long' típusú mérethez és memóriaelrendezéshez
enum class Color : long {
RED,
GREEN,
BLUE
};
// forward declaration. deklaráció. Ha később olyan értékeket
// definiálunk, amelyek nem illenek a 'char'-ba, az hibát jelez.
enum class Shapes : char;
Go
[szerkesztés]A Go az iota kulcsszót használja felsorolt konstansok létrehozásához.[12][13]
type ByteSize int
const (
_ = iota // ignore first value by assigning to blank identifier; 0
KB ByteSize = 1 << (10 * iota) // 1 << (10 * 1) == 1 << 10 == 1024; in binary 10000000000
MB // 1 << (10 * 2) == 1048576; in binary 100000000000000000000
GB // 1 << (10 * 3) == 1073741824; in binary 1000000000000000000000000000000
)
Java
[szerkesztés]A Java programozási nyelv J2SE 5.0-s verziója felsorolt típusokat adott hozzá, amelyek deklarációs szintaxisa hasonló a C nyelvéhez:
enum CardSuit {
CLUBS,
DIAMONDS,
SPADES,
HEARTS
};
CardSuit trump;
A Java típusrendszer azonban a felsorolásokat az egész számoktól elkülönített típusként kezeli, és az enum és int értékek keverése nem megengedett. Valójában egy enum típus a Javában egy speciális, fordító által generált osztály, nem pedig egy aritmetikai típus, és az enum értékek az osztály globális, előre generált példányaiként viselkednek. Az enum típusoknak lehetnek példánymetódusaik és egy konstruktoruk (amelynek argumentumai külön megadhatók minden enum értékhez). Minden enum típus implicit módon kiterjeszti az Enum absztrakt osztályt, így egy enum nem bővíthet semmi mást. Egy enum típus nem példányosítható közvetlenül.[14]
Belsőleg minden enum érték egy egész számot tartalmaz, amely megfelel a forráskódban deklarált sorrendjüknek, 0-tól kezdve. A programozó nem adhat meg közvetlenül egyéni egész számot egy enumerációs értékhez, de definiálhat túlterhelt konstruktorokat,[15] amelyek ezután tetszőleges értékeket rendelhetnek az enum osztály öndefiniált tagjaihoz. A getterek definiálása lehetővé teszi az öndefiniált tagok elérését. A belső egész szám lekérdezhető egy enumerációs értékből az ordinal() metódussal, és egy felsorolástípus enumerációs értékeinek listája sorrendben lekérdezhető a values() metódussal. Általában nem ajánlott a programozóknak az enumerációkat egész számokká és fordítva konvertálni.[16] A felsorolt típusok összehasonlíthatók, a belső egész szám használatával; ennek eredményeként rendezhetők.
A Java szabványos könyvtára segédprogramosztályokat biztosít a felsorolásokhoz. Az EnumSet osztály egy felsorolási értékek halmazát (Set) valósítja meg; bittömbként van megvalósítva, ami nagyon kompakttá és ugyanolyan hatékonysá teszi, mint az explicit bitmanipuláció, de biztonságosabbá is teszi. Az EnumMap osztály egy felsorolási értékek objektumhoz való leképezését (Map) valósítja meg. Tömbként van megvalósítva, ahol az felsorolási érték egész értéke szolgál indexként.
A C++-szal ellentétben a Java enumok tartalmazhatnak metódusokat, konstruktorokat és mezőket, mint bármely más osztály.
public enum Planet {
// Planet, followed by mass and radius
MERCURY(3.303e+23, 2.4397e6),
VENUS(4.869e+24, 6.0518e6),
EARTH(5.976e+24, 6.37814e6),
MARS(6.421e+23, 3.3972e6),
JUPITER(1.9e+27, 7.1492e7),
SATURN(5.688e+26, 6.0268e7),
URANUS(8.686e+25, 2.5559e7),
NEPTUNE(1.024e+26, 2.4746e7);
public static final double G = 6.67300E-11;
private final double mass;
private final double radius;
Planet(double mass, double radius) {
this.mass = mass;
this.radius = radius;
}
private double mass() {
return mass;
}
private double radius() {
return radius;
}
double surfaceGravity() {
return G * mass / (radius * radius);
}
double surfaceWeight(double otherMass) {
return otherMass * surfaceGravity();
}
public static void main(String[] args) {
double earthWeight = Double.parseDouble(args[0]);
double mass = earthWeight / EARTH.surfaceGravity();
for (Planet p : Planet.values()) {
System.out.printf("Your weight on %s is %f%n",
p, p.surfaceWeight(mass)
);
}
}
}
Perl
[szerkesztés]A C szintaktikai hagyományát követő dinamikusan típusozott[17] nyelvek (pl. Perl vagy JavaScript) általában nem biztosítanak felsorolásokat. A Perl programozásban azonban ugyanez az eredmény érhető el a rövidített karakterlánc-listával és hash-ekkel (esetleg szeletekkel[18]):
my @enum = qw(Clubs Diamonds Hearts Spades);
my( %set1, %set2 );
@set1{@enum} = (); # all cleared
@set2{@enum} = (1) x @enum; # all set to 1
$set1{Clubs} ... # false
$set2{Diamonds} ... # true
Raku
[szerkesztés]A Raku (korábbi nevén Perl 6) támogatja a felsorolásokat. A felsorolások deklarálására többféleképpen is lehetőség van a Rakuban, mindegyik egy háttér-térképet (back-end Map) hoz létre.
enum Cat <sphynx siamese bengal shorthair other>; # Using "quote-words"
enum Cat ('sphynx', 'siamese', 'bengal', 'shorthair', 'other'); # Using a list
enum Cat (sphynx => 0, siamese => 1, bengal => 2, shorthair => 3, other => 4); # Using Pair constructors
enum Cat (:sphynx(0), :siamese(1), :bengal(2), shorthair(3), :other(4)); # Another way of using Pairs, you can also use `:0sphynx`
PHP
[szerkesztés]Az felsorolt típost a PHP 8.1-es verziójában adták hozzá.
enum CardSuit
{
case Hearts;
case Diamonds;
case Clubs;
case Spades;
}
A felsorolók mögött állhatnak karakterlánc vagy egész számok a szerializálás elősegítése érdekében:[19]
enum CardSuit: string
{
case Hearts = 'H';
case Diamonds = 'D';
case Clubs = 'C';
case Spades = 'S';
}
Az Enum felülete elérhetővé tesz egy metódust, amely a felsorolóinak és azok nevének gyűjteményét adja meg. A karakterlánc/egész szám alapú Enumok a háttérértéket és a metódusokat is elérhetővé teszik (a deszerializálási kísérletnek). A felhasználók további metódusokat is hozzáadhatnak.
Rust
[szerkesztés]Bár a Rust a C-hez hasonlóan az enum kulcsszót használja, címkézett uniók[1] leírására használja, amelyek közül az enumok degenerált formának tekinthetők. A Rust enum-jai ezért sokkal rugalmasabbak, és struktúra- és tuple-változatokat tartalmazhatnak.
enum Message {
Quit,
Move { x: i32, y: i32 }, // struct
Write(String), // single-element tuple
ChangeColor(i32, i32, i32), // three-element tuple
}
A C-hez hasonlóan a Rust is támogatja az egyes változatok értékeinek megadását.
pub enum Weekday {
Sunday = 1,
Monday = 2,
Tuesday = 4,
Wednesday = 8,
Thursday = 16,
Friday = 32,
Saturday = 64,
}
Swift
[szerkesztés]A C nyelven a felsorolások kapcsolódó neveket rendelnek egy egész számok halmazához. A Swift nyelven a felsorolások sokkal rugalmasabbak, és nem kell minden felsorolási esethez értéket megadniuk. Ha minden felsorolási esethez megadunk egy értéket (raw value; nyers értéknek nevezzük), az érték lehet karakterlánc, karakter, vagy bármilyen egész vagy lebegőpontos típusú érték.
Alternatív megoldásként a felsorolási esetek megadhatják bármilyen típusú társított értékeket, amelyeket minden egyes esetértékkel együtt tárolni kell, hasonlóan ahhoz, ahogyan az uniók vagy variánsok teszik más nyelvekben. Egy felsorolás részeként definiálható a kapcsolódó esetek közös halmaza, amelyek mindegyikéhez egy másik, megfelelő típusú értékkészlet tartozik.
A Swiftben a felsorolások első osztályú típusok. Számos olyan funkciót alkalmaznak, amelyeket hagyományosan csak az osztályok támogattak, például számított tulajdonságokat, amelyek további információkat nyújtanak a felsorolás aktuális értékéről, és példánymetódusokat, amelyek a felsorolás által képviselt értékekkel kapcsolatos funkciókat biztosítanak. A felsorolások inicializátorokat is definiálhatnak, amelyek kezdeti esetértéket adnak meg, és kiterjeszthetők, hogy funkcionalitásukat az eredeti implementációjukon túl is kibővítsék; és megfelelhetnek a protokolloknak a szabványos funkcionalitás biztosítása érdekében.
enum CardSuit {
case clubs
case diamonds
case hearts
case spades
}
A C és az Objective-C nyelvekkel ellentétben a Swift felsorolási esetek létrehozásakor nem kapnak alapértelmezett egész értéket. A fenti CardSuit példában a clubs, diamonds, hearts, és spades ("treff", "káró", "kőr" és "pikk") nem implicit módon egyenlő 0-val, 1-gyel, 2-vel és 3-mal. Ehelyett a különböző felsorolási esetek önálló, teljes értékű értékek, explicit módon definiált CardSuit típussal.
Több eset is szerepelhet egyetlen sorban, vesszővel elválasztva:
enum CardSuit {
case clubs, diamonds, hearts, spades
}
Amikor olyan felsorolásokkal dolgozunk, amelyek egész vagy karakterlánc nyers (raw) értékeket tárolnak, nem kell explicit módon nyers értéket rendelni minden egyes esethez, mivel a Swift automatikusan hozzárendeli az értékeket.
Például, ha egész számokat használunk nyers értékekhez, az egyes esetek implicit értéke eggyel nagyobb, mint az előző eseté. Ha az első esetnek nincs beállított értéke, akkor az értéke 0. A CardSuit példában a színek 1-től kezdődően számozhatók a következőképpen:
enum CardSuit {
case clubs = 1, diamonds, hearts, spades
}
TypeScript
[szerkesztés]A TypeScript egy 'enum' adattípust ad hozzá a JavaScripthez.
enum CardSuit {
Clubs,
Diamonds,
Hearts,
Spades
};
var c: CardSuit = CardSuit.Diamonds;
Alapértelmezés szerint a tagok számát nullától kezdődően sorolja fel; ez felülírható az első értékének beállításával:
enum CardSuit {
Clubs = 1,
Diamonds,
Hearts,
Spades
};
var c: CardSuit = CardSuit.Diamonds;
Minden érték beállítható:
enum CardSuit {
Clubs = 1,
Diamonds = 2,
Hearts = 4,
Spades = 8
};
var c: CardSuit = CardSuit.Diamonds;
A TypeScript támogatja a numerikus érték nevéhez való leképezését. Például ez megkeresi a 2-es érték nevét:
enum CardSuit {
Clubs = 1,
Diamonds,
Hearts,
Spades
};
var suitName: string = CardSuit[2];
alert(suitName);
Python
[szerkesztés]A Python szabványos könyvtárához a 3.4-es verzióban egy enum modul került hozzáadásra. Bemutatja az Enum osztályt, amely kiterjeszthető felsorolt típusok definiálására.
from enum import Enum
class CardSuit(Enum):
CLUBS: int = 1
DIAMONDS: int = 2
HEARTS: int = 3
SPADES: int = 4
Létezik egy funkcionális API is, amely automatikusan generált indexekkel rendelkező felsorolásokat hoz létre (egytől kezdve):
Cards: Enum = Enum("Cards", "CLUBS DIAMONDS HEARTS SPADES")
A Python felsorolások nem kényszerítik ki a szemantikai helyességet (egy értelmetlen összehasonlítás egy inkompatibilis felsorolással mindig False értéket ad vissza, ahelyett, hogy TypeError hibát okozna):
Color: Enum = Enum("Color", "RED GREEN BLUE")
Shape: Enum = Enum("Shape", ["CIRCLE", "TRIANGLE", "SQUARE", "HEXAGON"])
def has_vertices(shape: Enum) -> bool:
return shape != Shape.CIRCLE
if __name__ == "__main__":
has_vertices(Color.GREEN)
# outputs "True"
Dart
[szerkesztés]A Dart támogatja a felsorolásokok legalapvetőbb formáját, és szintaxisa hasonló a többi enumokat támogató nyelvhez.
enum CardSuit {
Clubs,
Diamonds,
Hearts,
Spades
}
void main() {
CardSuit card = CardSuit.Clubs;
// Dart uses the "switch" operator to match the value of an enum with the desired output.
switch (card) {
case CardSuit.Clubs: {
print("Clubs");
}
break;
case CardSuit.Diamonds: {
print("Diamonds");
}
break;
case CardSuit.Hearts: {
print("Hearts");
}
break;
case CardSuit.Spades: {
print("Spades");
}
break;
default: {
print("Unknown");
}
break;
}
}
Megjegyzendő, hogy a Dart 3[20] előtt a switch operátor nem garantálta az esetek teljességét. Ez azt jelenti, hogy ha kihagyunk egy esetet, a fordító nem fog hibát jelezni.
Egyéb programozási nyelvek
[szerkesztés]COBOL
[szerkesztés]A COBOL nyelvben a feltételváltozó egy normál változó, amelynek alárendelt 88-as szintű mezői vannak, amelyeket feltételneveknek (condition-name) nevezünk. Minden feltételnévhez tartoznia kell egy VALUE záradéknak. A feltételzáradék VALUE záradéka megadhat egyetlen értéket vagy értékek listáját.
Fortran
[szerkesztés]A Fortran csak felsorolt típusokkal rendelkezik a C-vel való együttműködéshez; ezért a szemantika hasonló a C-hez, és a C-hez hasonlóan a felsorolt értékek csak egész számok, és nincs további típusellenőrzés. A fenti C példa Fortranban a következőképpen írható fel:
enum, bind( C )
enumerator :: CLUBS = 1, DIAMONDS = 2, HEARTS = 4, SPADES = 8
end enum
Microsoft Visual Basic family
[szerkesztés]| Visual Basic (classic) és VBA | VB.NET | VBScript |
|---|---|---|
Enum CardSuit ' Zero-based
Clubs
Diamonds
Hearts
Spades
End Enum
Sub EnumExample()
Dim suit As CardSuit
suit = Diamonds
MsgBox suit
End Sub
A felsorolt adattípusok automatikusan a " |
Enum CardSuit
Clubs
Diamonds
Hearts
Spades
End Enum
Sub EnumExample()
Dim suit As CardSuit
suit = CardSuit.Diamonds
MessageBox.show(suit)
End Sub
|
Not available |
Lisp
[szerkesztés]A Common Lisp a tagtípus-specifikátort használja, pl.:
(deftype cardsuit ()
'(member club diamond heart spade))
...amely kimondja, hogy az objektum cardsuit típusú, ha #'eql a club, diamond, heart vagy spade értékekkel szemben. A tagtípus-specifikátor azonban nem érvényes Common Lisp Object System (CLOS) paraméter-specializálóként. Ehelyett az (eql atom) használható, amely a (member atom) megfelelője (azaz a halmaznak csak egy tagja adható meg egy eql típusspecifikátorral, azonban CLOS paraméter-specializálóként használható). Más szóval, egy felsorolt típus lefedésére szolgáló metódusok definiálásához az adott típus minden egyes elemére definiálni kell egy metódust.
Továbbá,
(deftype finite-element-set-type (&rest elements)
`(member ,@elements))
futásidejű tetszőleges felsorolt típusok definiálására használható. Például:
(finite-element-set-type club diamond heart spade)
a CardSuit korábbi definíciójával egyenértékű típusra utalna, mivel természetesen egyszerűen a következőt használták volna:
(member club diamond heart spade)
de stilisztikai okokból kevésbé zavaró lehet a #'member függvénnyel.
Algebrai adattípus a funkcionális programozásban
[szerkesztés]Az ML vonalába tartozó funkcionális programozási nyelvekben (pl. Standard ML (SML), OCaml és Haskell) egy csak nulláris konstruktorokat[21] tartalmazó algebrai adattípus[22] használható egy felsorolt típus megvalósítására. Például (az SML jelőlések szintaxisában):
datatype cardsuit = Clubs | Diamonds | Hearts | Spades
type card = { suit: cardsuit; value: int }
val hand : card list
val trump : cardsuit
Ezekben a nyelvekben a kis egész számok (small-integer) reprezentációja teljesen rejtve van a programozó elől, ha a megvalósítás egyáltalán alkalmaz ilyen reprezentációt. A Haskell azonban rendelkezik az Enum típusosztállyal, amelyet egy típus levezethet vagy megvalósíthat, hogy megfeleltetést kapjon a típus és az Int között.
Adatbázisok
[szerkesztés]Néhány adatbázis közvetlenül támogatja az felsorolt típusokat. A MySQL egy felsorolt ENUM típust biztosít, amelynek megengedett értékei karakterláncként vannak megadva egy tábla létrehozásakor. Az értékek numerikus indexekként tárolódnak, ahol az üres karakterlánc 0, az első karakterlánc értéke 1, a második string értéke 2 stb. Az értékek numerikus indexként vagy karakterláncértékként tárolhatók és kérhetők le.[23]
Példa:
CREATE TABLE shirts (
name VARCHAR(40),
size ENUM('x-small', 'small', 'medium', 'large', 'x-large')
);
JSON Schema
[szerkesztés]JSON Schema-ban definiálható az "enum" kulcsszó használatával.[24]
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"cardsuit": {
"type": "string",
"enum": ["Clubs", "Diamonds", "Hearts", "Spades"]
}
},
"required": ["cardsuit"]
}
XML Schema
[szerkesztés]Az XML Schema támogatja a felsorolt típusokat a felsorolási aspektuson keresztül, amelyet a legtöbb primitív adattípus, például a karakterláncok korlátozására használnak.
<xs:element name="cardsuit">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="Clubs"/>
<xs:enumeration value="Diamonds"/>
<xs:enumeration value="Hearts"/>
<xs:enumeration value="Spades"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
Megjegyzések
[szerkesztés]Jegyzetek
[szerkesztés]- ↑ a b c A címkézett unió (tagged union), más néven variánsrekord, választási típus, diszjunkt unió vagy összegtípus egy olyan adatstruktúra, amely egy olyan érték tárolására szolgál, amely több különböző, de rögzített típust vehet fel.
- ↑ A névleges számok olyan számok, amelyeket címkékként használnak az elemek egyedi azonosítására. A számok tényleges értékei, amelyeket ezek a számok képviselnek, kevésbé relevánsak, mivel nem jelzik a mértéket, a rangot vagy bármilyen más mértékegységet.
- ↑ Highway to hell: C++ enums and bit fields › Wander Lairson Costa. walac.github.io. (Hozzáférés: 2025. szeptember 26.)
- ↑ Enterprise PL/I for z/OS 6.2 Language Reference. IBM, 28-29. o.. SC31-5716-00 (2025)
- ↑ The C Programming Language, 1st, Englewood Cliffs, NJ: Prentice Hall (1978. február 1.). ISBN 0-13-110163-3
- ↑ WG14-N3030 : Enhancements to Enumerations, 2022. július 19.
- ↑ Enum.HasFlag(Enum) Method (System) (amerikai angol nyelven). learn.microsoft.com. (Hozzáférés: 2024. december 6.)
- ↑ A számítástechnikában a szintaktikai cukor (syntactic sugar) egy programozási nyelven belüli szintaxis, amelynek célja, hogy megkönnyítse a dolgok olvasását vagy kifejezését. A nyelv „édesebbé” válik az emberi használat számára: a dolgokat világosabban, tömörebben vagy olyan alternatív stílusban lehet kifejezni, amelyet egyesek jobban kedvelnek.
- ↑ Obasanjo, Dare: A Comparison of Microsoft's C# Programming Language to Sun Microsystems' Java Programming Language, 2007. [2012. szeptember 10-i dátummal az eredetiből archiválva]. (Hozzáférés: 2012. szeptember 6.) „Javában az enumerált típusok teljes értékű osztályok, ami azt jelenti, hogy típusbiztosak, és metódusok, mezők hozzáadásával, vagy akár interfészek megvalósításával is bővíthetők. Míg C#-ban egy felsorolt típus egyszerűen egy szintaktikai cukor egy integrál típus (jellemzően egy int) körül, ami azt jelenti, hogy nem bővíthetők, és nem típusbiztosak.”
- ↑ Java 5: Taming the Tiger: Syntactic Sugar (német nyelven). Fachhochschule Aargau, Nordwestschweiz, 2005. április 8. [2007. január 7-i dátummal az eredetiből archiválva]. (Hozzáférés: 2012. szeptember 10.) „A felsorolások a Java 1.5 titkos nyertesei. Miután a Sun számos biztosítékot adott arra, hogy az felsorolások feleslegesek Javában, és könnyen lemásolhatók, végre bevezették őket. Az évszakok felsorolásának legegyszerűbb módja a következő: Az enum kulcsszó egy speciális osztálytípust jelöl, amely egy felsorolást definiál. ... "Más programozási nyelvekkel, például a C/C++-val és a C#-val ellentétben nem rendelhetünk hozzájuk egész számokat egyenlőségjel használatával."” Alt URL Archiválva 2013. május 27-i dátummal a Wayback Machine-ben.
- ↑ Syntactic sugar (C#): Enum. CSTrüter, 2011. augusztus 4. [2007. január 7-i dátummal az eredetiből archiválva]. (Hozzáférés: 2012. szeptember 10.) „// Rosszul megtervezett enum ne tegye ezt … Nyilvánvalóan (mint minden mással), ezt a cukrot is rosszul használhatjuk, ami egy hiperglikémiás rendszerhez vezethet. … Mivel az enum alapjául szolgáló típus egy int (más egész típusokat is használhatunk), érdekes problémákhoz vezethet, ha egy enumot bitjelzőként használunk bitenkénti operátorokon keresztül.”
- ↑ Effective Go. golang.org. The Go Authors. (Hozzáférés: 2014. május 13.)
- ↑ Go Wiki: Iota - The Go Programming Language (angol nyelven). go.dev. (Hozzáférés: 2025. május 15.) „A Go iota azonosítóját a konstans deklarációkban használják a növekvő számok definícióinak egyszerűsítésére. Mivel kifejezésekben is használható, az egyszerű felsorolásokon túlmutató általánosságot biztosít.”
- ↑ Enum Types. Oracle. (Hozzáférés: 2013. december 5.)
- ↑ Néhány programozási nyelvben a függvény túlterhelés function overloading vagy metódus túlterhelés azt a képességet jelenti, hogy több, azonos nevű függvényt hozzunk létre különböző implementációkkal. Egy túlterhelt függvény hívása a függvény egy adott implementációját futtatja, amely megfelel a hívás kontextusának, lehetővé téve, hogy egy függvényhívás a kontextustól függően különböző feladatokat hajtson végre.
- ↑ Bloch, Joshua. Effective Java, Second, Upper Saddle River, N.J.: Addison-Wesley, 158. o. (2008). ISBN 978-0-321-35668-0
- ↑ A dinamikus típusellenőrzés egy program típusbiztonságának futásidejű ellenőrzésére szolgáló folyamat. A dinamikusan típusellenőrzött nyelvek implementációi általában minden futásidejű objektumot egy típuscímkével (azaz egy típusra mutató hivatkozással) társítanak, amely a típusinformációit tartalmazza.
- ↑ A számítógépes programozásban a tömbszeletelés egy olyan művelet, amely egy tömb elemeinek egy részhalmazát kinyeri, és egy másik tömbként csomagolja be, esetleg az eredetitől eltérő dimenzióban.
- ↑ A számítástechnikában a szerializálás (más néven pickling a Pythonban) az a folyamat, amelynek során egy adatszerkezetet vagy objektumállapotot olyan formátumra fordítanak, amely tárolható (pl. fájlok másodlagos tárolóeszközökön, adatpufferek elsődleges tárolóeszközökön) vagy továbbítható (pl. adatfolyamok számítógépes hálózatokon keresztül), és később rekonstruálható (esetleg egy másik számítógépes környezetben).
- ↑ language/accepted/3.0/patterns/exhaustiveness.md at main · dart-lang/language (angol nyelven). GitHub. [2024. december 3-i dátummal az eredetiből archiválva]. (Hozzáférés: 2025. június 20.)
- ↑ A számítógépes programozásban a nullary constructor olyan konstruktor, amely nem fogad el argumentumokat.
- ↑ A számítógépes programozásban, különösen a funkcionális programozásban és a típuselméletben, az algebrai adattípus (ADT - algebraic data type) egy összetett adattípus – egy olyan típus, amelyet más típusok kombinálásával hoznak létre. Egy algebrai adattípust két fő szerkezet definiál: egy összeg és egy szorzat. Ezeket néha "OR" és "AND" típusoknak is nevezik.
- ↑ MySQL :: MySQL 8.0 Reference Manual :: 11.3.5 The ENUM Type. dev.mysql.com. (Hozzáférés: 2021. szeptember 19.)
- ↑ JSON Schema Validation: A Vocabulary for Structural Validation of JSON (angol nyelven). json-schema.org. (Hozzáférés: 2025. június 22.)
Fordítás
[szerkesztés]- Ez a szócikk részben vagy egészben az Enumerated type című angol Wikipédia-szócikk ezen változatának fordításán alapul. Az eredeti cikk szerkesztőit annak laptörténete sorolja fel. Ez a jelzés csupán a megfogalmazás eredetét és a szerzői jogokat jelzi, nem szolgál a cikkben szereplő információk forrásmegjelöléseként.