Le enumerazioni HaXe sono tipi di dati algebrici (ADT). Il tuo esempio in Haskell:
data Color3
= Red
| Green
| Blue
| Grey { v :: Int }
| Rgb { r, g, b :: Int }
| Alpha { a :: Int, col :: Color3 }
In entrambe le lingue, questo tipo esprime semplicemente che un Color3
ha alcuni valori possibili: rosso, verde o blu; un valore grigio; un valore RGB arbitrario; oppure un valore Color3
con un canale alfa aggiuntivo. Il fatto che alcuni di questi costruttori adottino parametri aggiuntivi non dovrebbe essere allarmante. È semplicemente un analogico chiuso terso con il comportamento dell'eredità aperto :
class Color3 {}
class Red : Color3 {}
class Green : Color3 {}
class Blue : Color3 {}
class Grey : Color3 {
public var v:int;
public function Grey(v:int) {
this.v = v;
}
}
class Rgb : Color3 {
public var r:int, g:int, b:int;
public function Rgb(r:int, g:int, b:int) {
this.r = r;
this.g = g;
this.b = b;
}
}
class Alpha : Color3 {
public var a:int;
public var col:Color3;
public function Alpha(a:int, col:Color3) {
this.a = a;
this.col = col;
}
}
Qui chiunque può venire e aggiungere una nuova classe child Color3
che possa o meno rispettare le proprietà che vogliamo applicare. Con le enumerazioni parametrizzate abbiamo il controllo centrale su tutti i costruttori e abbiamo anche la corrispondenza del modello:
return switch (c) {
case Red: 0xFF0000;
case Green: 0x00FF00;
case Blue: 0x0000FF;
case Grey(v): (v << 16) | (v << 8) | v;
case Rgb(r,g,b): (r << 16) | (g << 8) | b;
case Alpha(a,c): (a << 24) | (toInt(c) & 0xFFFFFF);
}
Contrastare l'alternativa di aggiungere un metodo toInt()
a ogni sottoclasse di Color3
. Sarebbe molto più codice, portando a un maggior potenziale di errori.
Si noti che questo particolare esempio non è eccezionale perché alcuni dei costruttori sono ridondanti: Rgb
subsumes Red
, Green
, Blue
e Grey
, e Alpha
può essere applicato a un colore che ha già Alpha
, che potrebbe non essere desiderabile.