programmez-en-d/null_is.whata

220 lines
7.7 KiB
Plaintext
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

[set
title = "La valeur [c null] et l'Opérateur [c is]"
partAs = chapitre
translator = "Raphaël Jakse"
proofreader = "Stéphane Goujet"
]
Dans le chapitre précédent, nous avons vu qu'une variable d'un type référence n'a pas besoin de référencer un objet :
[code=d <<<
MaClasse referenceUnObjet = new MaClasse;
MaClasse variable; // ne référence pas un objet
>>>]
Étant d'un type par référence, [c variable] a, dans le code précédent, une identité mais ne référence pas encore d'objet. Un tel objet peut être représenté comme ceci dans sa case mémoire~ :
[pre <<<
variable
---+------+---
| null |
---+------+---
>>>]
Une référence qui ne référence aucune valeur est [c null]. Nous développerons ce point.
Une telle variable est dans un état quasiment inutile. Comme elle ne référence pas d'objet, elle ne peut pas être utilisée dans un contexte où un objet [c MaClasse] est requis~ :
[code=d <<<
import std.stdio;
class MaClasse
{
int membre;
}
void utiliser(MaClasse variable)
{
writeln(variable.membre); // ← BOGUE
}
void main()
{
MaClasse variable;
utiliser(variable);
}
>>>]
Il n'y a pas d'objet référencé par le paramètre que la fonction [c utiliser] reçoit. Essayer d'accéder à un membre d'un objet non existant fait planter le programme~ :
[code <<<
$ ./essai
$ Erreur de segmentation
>>>]
«~ Erreur de segmentation~ » est une indication que le programme a été tué par le système d'exploitation parce qu'il a essayé d'accéder à une adresse mémoire illégale.
[ = La valeur [c null]
La valeur spéciale [c null] peut être affichée comme n'importe quelle autre valeur.
[code=d <<<
writeln(null); // affiche 'null' dans la sortie
>>>]
Comme dans beaucoup d'autres langages, la représentation entière de [c null] est 0.
Une variable [c null] peut être utilisée dans deux contextes~ :
# [
En lui affectant un objet
[code=d <<<
variable = new MaClasse; // référence maintenant un objet
>>>]
Cette affectation fait pointer [c variable] vers l'objet nouvellement créé. À partir de là, [c variable] peut être utilisée pour n'importe quelle opération valide du type [c MaClasse].
]
# [
Pour déterminer si elle est [c null].
Cependant, comme l'opérateur [c ==] a besoin de deux objets pour faire la comparaison, l'expression qui suit ne peut pas être compilée~ :
[code=d <<<
if (variable == null) // ERREUR de compilation
>>>]
Pour cette raison, pour savoir si une variable est [c null], on utilise l'opérateur [c is].
]
]
[ = L'opérateur [c is]
Cet opérateur répond à la question "a la valeur nulle ?" (NdT : ''is'' veut dire «~ est~ » en anglais)~ :
[code=d <<<
if (variable is null) {
// Ne référence aucun objet
}
>>>]
L'opérateur [c is] peut aussi être utilisé avec d'autres types de variable. Dans l'utilisation suivante, il compare les valeurs de deux entiers~ :
[code=d <<<
if (vitesse is nouvelleVitesse) {
// Leurs valeurs sont égales
} else {
// Leurs valeurs sont différentes
}
>>>]
Lorsqu'on l'utilise avec les tranches, il détermine si deux tranches référencent le même ensemble d'éléments~ :
[code=d <<<
if (tranche is tranche2) {
// Elles donnent accès aux mêmes éléments
}
>>>]
]
[ = L'opérateur [c !is]
[c !is] est l'opposé de [c is]. Il donne [c true] quand les valeurs sont différentes~ :
[code=d <<<
if (vitesse !is nouvelleVitesse) {
// Leurs valeurs sont différentes
}
>>>]
]
[ = Affecter la valeur [c null]
Affecter la valeur [c null] à une variable de type référence fait que la variable arrête de référencer son objet actuel.
S'il se trouve que cette affectation supprime la dernière référence à cet objet, alors l'objet devient un candidat à la finalisation par le ramasse-miette. En effet, pour un objet, n'être référencé par aucune variable veut dire qu'il n'est pas utilisé du tout dans le programme.
Regardons l'exemple d'[[part:valeur_vs_reference |un chapitre précédent] où deux variables référençaient le même objet~ :
[code=d <<<
auto variable = new MaClasse;
auto variable2 = variable;
>>>]
Ce qui suit est une représentation de l'état de la mémoire après l'exécution de ce code~ :
[pre <<<
(objet MaClasse anonyme) variable variable2
---+-------------------+--- ---+---+--- ---+---+---
| ... | | o | | o |
---+-------------------+--- ---+-|-+--- ---+-|-+---
▲ | |
| | |
+--------------------+------------+
>>>]
Affecter la valeur [c null] à l'une des deux variables casse sa relation avec l'objet~ :
[code=d <<<
variable = null;
>>>]
À partir de ce point, il n'y a plus que [c variable2] qui référence l'objet~ :
[pre <<<
(objet MaClasse anonyme) variable variable2
---+-------------------+--- ---+------+--- ---+---+---
| ... | | null | | o |
---+-------------------+--- ---+------+--- ---+-|-+---
▲ |
| |
+------------------------------------+
>>>]
Affecter [c null] à la dernière référence rendrait l'objet inatteignable~ :
[code=d <<<
variable2 = null;
>>>]
Un tel objet inatteignable sera finalisé par le ramasse-miette à un certain moment dans le futur. Du point de vue du programme, l'objet n'existe pas~ :
[pre <<<
variable variable2
---+-------------------+--- ---+------+--- ---+------+---
| | | null | | null |
---+-------------------+--- ---+------+--- ---+------+---
>>>]
Nous avons discuté des moyens de vider un tableau associatif dans les exercices du [[part:tableaux_associatifs | chapitre sur les tableaux associatifs]. Nous connaissons maintenant une quatrième méthode~ : affecter [c null] à un tableau associatif casse la relation entre cette variable et les éléments~ :
[code=d <<<
string[int] noms;
// ...
noms = null; // Ne donne accès à aucun élément
>>>]
De manière similaire aux exemples avec [c MaClasse], si [c noms] était la dernière référence aux éléments du tableau associatif, ces éléments seront finalisés par le ramasse-miette.
Les tranches peuvent également être affectées à [c null]~ :
[code=d <<<
int[] tranche = autreTranche[ 10 .. 20 ];
// ...
tranche = null; // Ne donne accès à aucun élément
>>>]
]
[ = Résumé
- [c null] est la valeur indiquant qu'une variable ne donne accès à aucun élément.
- Les références qui ont la valeur [c null] ne peuvent être utilisées que dans deux opérations~ : leur affecter une valeur et déterminer si elle sont [c null] ou pas.
- Comme l'opérateur [c ==] peut nécessiter l'accès à un objet, déterminer si une variable est [c null] doit être fait avec l'opérateur [c is].
- [c !is] est l'opposé de [c is].
- Affecter [c null] à une variable fait que cette variable ne pointe plus vers aucun objet.
- Les objets qui ne sont référencés par aucune variable sont finalisés par le ramasse-miette.
]