web-dev-qa-db-fra.com

Devez-vous définir une valeur null/unknown pour les énumérations Java?

Lorsque vous définissez une énumération pour quelque chose qui peut être "non défini" dans vos interfaces, devez-vous 

  • définir une valeur d'énumération distincte pour cela, ou 
  • utilisez simplement enumValue = null pour ces situations? 

Par exemple,

serviceX.setPrice (Price priceEnum)

enum Price {
 CHEAP, EXPENSIVE, VERRRY_EXPENSIVE, UNKNOWN
}

et priceEnum.UNKNOWN au besoin

ou 

enum Price {
 CHEAP, EXPENSIVE, VERRRY_EXPENSIVE
}

et priceEnum = null en cas de besoin?

Avoir un petit débat à ce sujet. Quelques points qui me viennent à l’esprit:

  • utiliser Price.UNKNOWN enregistre du code "if (price == null)". Vous pouvez gérer toutes les valeurs de Price x dans un seul commutateur 
  • En fonction de la technologie d'affichage, il peut être plus facile de localiser Price.UNKNOWN 
  • en utilisant Price.UNKNOWN genre de cause "problème de nombre magique" dans le code, IMO. Ici nous avons Price.UNKNOWN, ailleurs peut-être Color.UNDEFINED, Height.NULLVALUE, etc.
  • l'utilisation de priceValue = null est plus uniforme avec la façon dont les autres types de données sont gérés en Java. Nous avons Integer i = null, DomainObject x = null, String s = null pour les valeurs inconnues également, n'est-ce pas?
  • Price.UNKNOWN vous oblige à décider si la valeur null est autorisée de manière universelle pour tous les cas d'utilisation. Nous pouvons avoir la méthode Price getPrice () qui peut renvoyer Price.UNKNOWN et setPrice (Price p) qui n’est pas autorisé à accepter Price.UNKNOWN. Comme Price.UNKNOWN est toujours inclus dans les valeurs de l'énumération, ces interfaces sont un peu sales. Je sais que priceValue = null a le même problème (vous ne pouvez pas définir dans l'interface si null est accepté ou non), mais il semble un peu plus propre et un peu moins trompeur (?)
35
user449236

Ceci est en fait un exemple d'application Modèle d'objet Null . À mon humble avis, il est toujours préférable d'avoir un objet factice plutôt que null. Par exemple, vous pouvez ajouter des méthodes factices à null-object plutôt que de disperser votre code avec des contrôles nuls partout. Très pratique.

De plus, le nom de enum vous donne une sémantique supplémentaire: le prix est-il inconnu, undefined, pas digne de confiance, pas encore connu? Et qu'est-ce que cela signifie si le prix est null?

UPDATE: Comme le souligne Aaron Digulla, le modèle d'objet nul requiert de la mémoire. Mais ce n'est pas réellement le cas la plupart du temps. Dans l'implémentation traditionnelle, vous avez généralement un singleton pour l'objet Null utilisé partout, car il n'est pas nécessaire d'avoir des instances séparées. Cela devient encore meilleur avec les énumérations parce que vous obtenez la sémantique de singleton gratuitement.

Un autre point est que la référence null et la référence à un objet occupent la même quantité de mémoire (disons 4 octets sur une machine 32 bits). C'est l'objet référencé qui occupe de la mémoire supplémentaire. Mais s'il s'agit d'un singleton, il n'y a pratiquement pas de surcharge de mémoire ici.

27
Tomasz Nurkiewicz

Je dirais aller avec Price.UNKNOWN si c'est une valeur valable pour un prix.

Je suis d'accord avec les inconvénients liés aux références nulles que vous avez mentionnées, et je pense qu'elles motivent suffisamment la décision.

Les nouvelles langues, comme Scala par exemple (et certaines plus anciennes, Haskell), évitent toutes les références nulles et utilisent l’option/peut-être des monades à la place ... pour de bonnes raisons.

12
aioobe

Il y a le Enum-Switch-Null-Trap . Il semble donc que, comme pour toute propriété qui est un objet, S'il n'existe pas, il s'agit de null.

1
Avi Cohen

Cela dépend de la manière dont vous allez utiliser cette énumération. Si vous l'utilisez dans des instructions switch/case, cela n'a pas d'importance. Si vous créez une ou plusieurs méthodes dans l’énumération, vous devez définir INCONNU 

Par exemple, vous pouvez définir une méthode abstraite public abstract Icon icon();

dans votre enum et ensuite implémenter cette méthode pour chaque membre de Price. Vous voudrez probablement afficher un point d'interrogation pour un prix inconnu. Dans ce cas, implémentez simplement la méthode icon() qui crée l’icône appropriée. 

1
AlexR

Couleur ou Hauteur seraient utilisés dans la logique du programme. Ils ne peuvent pas manipuler avec une couleur indéfinie . Un prix est une donnée utilisateur et peut être inconnu . La couleur peut être une donnée utilisateur, mais, pour être utilisée comme couleur dans le code, elle doit être définie.

Donc, le prix peut être inconnu (au lieu de null), couleur non (null peut indiquer une erreur).

0
Nic Stray