So we could have like
ourUser.getOptionalAttributes()
// could return a list [Date Birthday, Float Height, Color Eyecolor]
// or just [Color Eyecolor]
// or even an empty list
Am i totally on the wrong track here and are option types the (philosophical) correct way to express optional attributes?
L'unica volta che l'uso di una lista ha senso è quando un determinato attributo può verificarsi da 0 a n > 1
volte. Non so nemmeno cosa pensi di fare con il primo esempio: quell'elenco è eterogeneo. (Non sto dicendo che non è possibile - potresti usare le classi dei casi in modo che ogni elemento dell'elenco abbia una data, un float o un colore, ma seriamente, che cosa ti spinge?)
Un tipo Maybe
/ Option
è fondamentalmente la cosa giusta per rappresentare Nothing
o un singolo valore di tipo T
. Se type T
ha n
valori distinti, Option <T>
ha n + 1
valori distinti; ed essendo un tipo distinto da T
, è un errore assegnare ciecamente un Option <T>
a T
nello stesso modo in cui è sbagliato ciecamente assegnare un numero a 64-bit a un 32 -bit numero.
Per segnalare errore in un calcolo, puoi in alternativa lanciare un'eccezione invece di restituire un Option
. Ciò è utile quando è probabile che un errore venga gestito più in alto nello stack di chiamate. È anche utile quando si passano le funzioni ad altre funzioni. Ad esempio, potresti avere una funzione A
che desidera una funzione B
che restituisca un intero. Potrebbe essere il caso che B
potrebbe teoricamente non riuscire a produrre un intero, ma hai assicurato che questo particolare uso di B
produrrà un risultato. Avere Option
nel tipo di ritorno di B
lo renderebbe incompatibile con A
.
Also, are there additional concepts for handling the logic of optional attributes other than nullable types and option-like types?
Esiste il concetto di dividere i valori del tuo tipo nelle classi dei casi appropriate. Come semplice esempio, supponiamo di lavorare con coordinate cartesiane e di dover lavorare con coordinate sia rettangolari che polari. Sebbene ci siano due rappresentazioni, è importante capire che entrambi rappresentano valori dello stesso tipo. Un modo ingenuo di implementare questo sarebbe:
public class Point2D {
public static enum Type { RECT, POLAR }
public Type type;
public Option<Double> x; // Rectangular coords
public Option<Double> y; // Rectangular coords
public Option<Double> angle; // Polar coords
public Option<Double> magnitude; // Polar coords
}
Ma questo approccio è sbagliato - non è che ogni campo (salvato per type
) sia facoltativo, è che ci sono due tipi di Point2D e tu hai unito i due. Se lo hai modellato correttamente utilizzando case classes , nessuno dei campi sarebbe facoltativo:
abstract class Point2D
case class Rect(x: double, y: double) extends Point2D
case class Polar(angle: double, magnitude: double) extends Point2D
Questo è più legato alla scelta del modello giusto piuttosto che ai valori "mancanti", ma lo accenno perché può portare all'uso errato di Option
(o null
, dio non voglia.)
Come altri hanno menzionato, c'è il concetto di Pattern a oggetti nulli , ma questo è legato alla semantica specifica del tipo. Un oggetto nullo non ha senso per alcuni tipi.