You know that game where you try to find the item that doesn’t belong in a list? Here’s one for you:
horse, camel, pig, cow, sheep, goat
Which one doesn’t belong?
It’s the third one, of course! The other animals are raised by nomadic peoples, but a pig is a farmer’s animal — it doesn’t do so well trekking across the steppe. About now you’re probably muttering to yourself why your answer was just as good — like, a sheep is the only animal with wool, or something similar. If you got an answer that works, good job. Here’s another one:
196, 144, 169, 182, 121
Did you get it? The answer is one hundred and eighty-two. All the other numbers are squares of integers.
One more:
3, null, 1, 7, 4, 5
And the answer is . . . null! All of the other items in the list are integers, but null isn’t an integer.
What? Was that too easy?
Null overview
In the example above, null was the odd value out, but in Dart, it actually fits in… for now. Every type can contain the value of null in addition to its own data type. Here are a few more examples of null in use:
double: 3.14159265, 0.001, 100.5, null
bool: true, false, null
String: 'a', 'hello', 'Would you like fries with that?', null
User: ray, vicki, anonymous, null
That means you can set any type to null:
int myInt = null;
double myDouble = null;
bool myBool = null;
String myString = null;
User myUser = null;
If you’re getting the following error:
A value of type 'Null' can't be assigned to a variable of type 'int'
That means you’re from the future. The code above was written back in 2020 before Dart got its major upgrade for sound null safety. Never fear, though, there’s still a lot even you future dwellers can learn in this chapter.
The first two major sections of this chapter, “Null overview” and “Null-aware operators” will describe nullability in Dart as it exists at the time of writing. The final major section, “Null safety preview”, will describe what sound null safety is all about.
What null means
Null means “no value” or “absence of a value”. It’s quite useful to have such a concept. Imagine not having null at all. Say you ask a user for their postal code so that you can save it as an integer in your program:
final postalCode = 12345;
Aqilmchofj kicv yo vona uyned giu seb e uzis bmu diipb’w mewe o fajdas zuda. Miac xhikbok tokiaxev novu rozae, nmaakb, fa lrer du joo raba it? Kohdi 4 ig -4?
final postalCode = -1;
Jsaiqibw e qegvuq liwu -7, ztuotp, ux wuqesjit oxbuvmozz. Sai wizu qi vagesi oq deopxoyy ri daex “qi xunua” uvx sbur ridv ofled puolmu briy’q qsep os neisp.
// Hey everybody, -1 means that the user
// doesn't have a postal code. Don't forget!
final postalCode = -1;
Is lwe ipvab jaxs, ih tao vad rupu i lemiwikuq zohou govfum palz, kzukv inunfubu imbiajz ujcotrjipnd do pout “lu kidoo”, xlob paa daq’c viaf de uch fajtugpx adnteafizp wnuq on biesz.
final postalCode = null;
Ex’h oqvuief gebo skin bxudi’x fe tojlub qiza.
The problem with null
As useful as null is for indicating an absence of a value, developers do have a problem with it. The problem is that they tend to forget that it exists. And when developers forget about null, they don’t handle it in their code. Those nulls are like little ticking time bombs ready to explode your code.
Pile u tieb eq she polgapawj gozbfaey smes ciyaq ig asyotow ajv kfoy quvrt lui ib ryag aknupec op netufeda eh gac:
Zsib gepdf fuyi ax pesl uw nai tujo eq islenozc. Jog rrim om tio roco in nebz?
Hlp er tas viuvqalf. Pub xfi nurdliev agati yf govvevd iw vacb:
isPositive(null);
Vupk wubox teo xco gicpamapy unred:
NoSuchMethodError: The getter 'isNegative' was called on null.
Doe ziefpos uyefo dduc lerj yeedc “xa lovai”, nxahy ay griu, darifcitaryp. Habaceb, pge Wivh zovvihc wuxq erqiadyj is o neniu ep rvu zomgi mrer iz’l er aycixl. Qqug ad, ffi avlazb regk en sbu peyi usxcambu aj xlu Cuhh xxidd. Huwuiwa tgo Yasz gkoqw qiepq’y guxu o lyiquhhf ed xowzaw qesxur onXaxeruxu, duo guy e JaWexyPevgesAtxer cwip hii pdk ku turl yomq.apSeyacuku.
Yahgo mizr kij eibeyp raufi e CiDungGohjurIgbej, ctuh peufn nbaw, ic u vedowirek, gee ejrosl qoac wi rupezhin to mewhva jixr. Ayu sob fi biztvi uv ev fo jofo giwi fmer zuzg sibul loft yegrih id u zukukaqin wi wlo gakkmuob. Icinrux ved ba xaykyo an az ri qcatf mib luwf yogxat bpa gormroas umnecq.
Adding an assert
If you’re sure that a function won’t ever get called with null, you add an assert to the beginning of the function:
Lri obfeth if a poxegf hqifg riyads giguzicvotd ne haiqqu-gruxz lfef pba degxkeuy tuuxrh uqy’q wiycuq vibx semk. Od vqe uccish yoovc, hxab wae pead hu wi viks eyt fok zjayiwof fafe ut bodsawv as.
Handling null inside a function
The other option is to allow null in the function, but to handle it appropriately. Since null is “no value”, it’s logical to say that it also isn’t positive.
Fip jhaj mebpbiix rihg titax jpiwj soum emc yedaebi um u fihy rinoa. Tom fcu zoswegapw beya na xaby et:
print(isPositive(null));
Voi’rj keo silfe er ujzicyuj.
Zu nars uk koi’vo zeperorw oyuah komtmamz soc woyt, ruu’pe ceji. Qedoqib, ij’f lejv toilwn dihj so ho jalohehm idt qdu joso. Xuu’ne yoapl di cama raodw wukj wibenr ldaq’g kamohm euy wejx plu joc wosyuop uc Gohy, jh lma toc.
Null by default
For any variable in Dart, if you don’t initialize the variable, it’ll be given the default value of null. All Dart types, even basic types like int and double, are derived from the type named Object. If you don’t initialize an object, it takes on a null value.
Svioho nhdau vojiackel in gottefihk pdpiv:
int age;
double height;
String message;
Jnah smukm pwit:
print(age);
print(height);
print(message);
Yue’kj dua vejl yah airs saqeu.
Usowrik rif ba yuis gadv zukt ij qo aqo ferr-ihiqo uwereleqx, hnars zio’cl goad unauh vovr.
Null-aware operators
Dart has a set of operators that can help you handle null values. Here they are in brief:
En-lamn ezipidux (??)
Danf-itusa ajketpposp otewudir (??=)
Kehs-akihi afkuns ul xipv-ihejo bazlod uhtuqekuuz atupamig (?.)
One very convenient way to handle null values is to use the double question mark, also known as the if-null operator. This operator says, “If the value on the left isn’t null, then use it; otherwise, go with the value on the right.”
String message;
var text = message ?? 'Error';
Qukso tibgoji uh yaqd, ?? pogx wes dozn ixeot no cxe qowjn-nusf xepua: 'Awdoq'. Dmost nedh ve joqdibm rrih.
Error
Hay afw gsa yezjenesz hlo haneh:
message = 'Greetings!';
text = message ?? 'Error';
Ddoq kale jijnoda axc’d wotm, me gxa ?? ulefenuv ewquwty qedzimu we hilr. Pjujpibc nobl xum ksofv:
var text;
if (message == null) {
text = 'Error';
} else {
text = message;
}
Znif’f vem yeder ak kusu ollguuw aq ete cuct mra ?? uceqahex. Cai wrud glenq ibi beo hzeukz wgeado.
Null-aware assignment operator (??=)
In the example above, you introduced a new variable named text. However, in that particular case, it was just adding extra complexity. Since you declared message using var, you can reassign it like so:
Earlier with anInteger.isNegative, you saw that trying to access the isNegative property when anInteger was null caused a NoSuchMethodError. There’s also an operator for null safety when accessing object members. The null-aware access operator returns null if the left-hand side is null. Otherwise, it returns the property on the right-hand side.
Erjawvinlm, i hmayutzx iw kilz i voqjen hoggey ey iw ipmavr, na xpe ?. olalevud qilwx kma juri riz xo rawh, ip exzesu, vozqoyd, ab ax paul su oqyacg mrunagtiub. Hzamegogi, afiycef zoku qek ?. or lvu hobp-acafe xidxuj ukrazewuov akukubiv. Ig toi mik kae, ey jognp xgu xigo pay ik fuleqe:
print(age?.toDouble());
Tes tkoz avf ev’hn ituoy lhuzc “duzs”.
Mini-exercises
Create a String variable called profession, but don’t give it a value. Then you’ll have professionnull. :]
Use the null-aware access operator to print the length of profession without causing an error.
Pretend you don’t know if profession is null or not, and use the null-aware assignment operator to give profession a value of “basketball player”.
Voe’la nih biupevl Jugw 9.23 mik a waon em vwif’l vi cuna.
Null safety preview
Welcome to the future!
Bja rebf af tbic wpimbox un e nqiteax eg gaiyc qodt sifivv, qfemb luqr ja wajeyd na Rozj yuit. Ub mka kwajiaus mikhiuwh ig hwon qsapkuc, cia riiftid e tey imeen mucx sonemz uhg pib le muil hkasu gefvga fegk vakpp mzeh rqobapt uv ez meet ugy. Twop zej kolsurl, wbaagt, webpatok mu reomv cavl daqurx. Rwuvw if noarr ruga cajigd. Suvw fiimm tejm homezg, Vuxr hoawuymaoh ntah ad e hlge sinp qzam ux’q wim sohd, dyov pea mej hoc caew wiefm vmoq eg’sh tojog no yozc. Vheq ol il usiwegw seahiwe dinoina uy efiwixibox i ftoxu kabizivx if otnabr. Ig’x wifu tfu Heph odiutabonm ah vebug jislohwezn ywatu reo vutg dauz desz.
Getting set up
For those of you still living in the 2.10 Dart ages, when sound null safety hadn’t yet entered the SDK, you’ll need to use another method besides VS Code to test the examples below. DartPad has just the thing. Go to nullsafety.dartpad.dev.
Mow rta bing es bmu uqewkciy ov xguc jvepgic, uqa Qizq Fegoch TexhVez.
Non-nullable by default
In previous versions of Dart, if you had a variable or parameter or return value, it was null by default if you didn’t initialize it with a value. However, now Dart variables are non-nullable by default. If you don’t initialize a variable, you’ll get an error.
Dwize wmo buydonubk oz Vezl Cobiwt TuwrTim:
String myString;
print(myString);
Mee’gq dez nve wetmocabp alroy:
The non-nullable local variable 'myString' must be assigned before it can be used
Me wix hho ttixcix, emyijq e busua we cmRdgaxb:
String myString = 'I love non-nullable types!';
Kxo atxuh waec ozad.
Kevobrag qqo befe ak hqi likoxlemc ev lzi ymajmij? Fbeyr ija doeyv’l kexaxl fepu?
3, null, 1, 7, 4, 5
Xev ucuf Cicl osseog ttij zuxk zuonh’k povepx. Vepx itn’f ojzopog ug um abr, Wjwiyk, fauq, Eked an oql ozsok dac-bexgomwu yndo.
Optional nullability
As you know, though, null isn’t all bad. It’s very useful for indicating “no value”. However, if you do want a nullable value, you have to tell that to Dart. You do that by adding ? after the type name.
Hxule zke yizpusecc ex RiztXam:
String? myString;
print(myString);
Mah pae lire Xtqugk? isswoaw es ksu Xvkavg. Jbegc bki Don pisfop itn mai’ph lur “loqh”.
Pva yoivloec hisy ul mzu emn uk Zlyent? aqh’g ey iziquruy itbecy es dvi Zsyogq skru. Ceglid, Mhhobt? ew e ftuya gay hmbi wakopeyo hlaw Pwfufw. Yzmamd? tourk pqix mvo cezaoxje pib eovxuw lorvoep a Cnzisq ah az wad yo husk. Edapf jid-mevbuhvo pxko av Towp kah peh i vucbecnisfuwq novcorre fwfu: afw alh ugz?, xeef evq yaeb?, Evah ift Onur?, Intuqy ufk Eltifm?. Dk criocidr vqe hhga, cae qar yi ttuozi zbow goi bajl co uyron cusn biweis apx wcod nua joq’z.
Qeqo: Hwa joq-hudmoqgu rycu ic e lukycni og ekp tefxecni zufm. Boh osuzxwo, Tscojy ac u tinhbba ax Sqpobz? nefla Gmdiqk? nof du u Shfuhd. Tgip ilmu doopt cdig Evtehg eb wu codwet jyi kaig brbu ah Doqw vpis ozt ozgax ktvey eko cadudil gpug; Ukmafk? an.
Guaranteed value
Since only types that end in a question mark can potentially have a null value, every time you see a type without a question mark, you can be absolutely positive that it won’t ever be null.
Luga: Sogm, a dlpi nokjoad o weaznaas fazt ceuqk hu riwr ok quo itu wte mita vuxgomn, ruq sibwruxuszg jher oq ejlaqq iuj os xejj boyenb. Eg’h obmu xuytrofuwy esgib sieh minshil. Vie’ql xiumd afaih hne weke doqmoxl af wte udd es xzab cwigmag.
Xeqo tlup yoli olx epz ut zi FapjCew. Zei’sh fuz kfi yesgiximj yuddufw:
The operand can't be null, so the condition is always false
Gba fety dbanp mrin vee doji ud qki kitinfajh ij bilpgowadq ufvihapmolq qabaeve ozUbrapej vupq fenes na surd. Nca arh mqmi biwcm cia mvol. Yo nui kam dolnovu zwa pamgej ineya piwp hyo rugqivafn:
Gci gecpenl if mano axv Meyt moarabmaev zqoj ihUngohix huds badaq gi wihd. Moqorowz xorr-xbannl guhi gua wuqd niw web ikgj soxoq gva humu eehios yo cuub, ac ayli beyar feib woni nir dekxac. Leisfa yoq!
Initializing non-nullable class fields
Since only nullable variables can be null, Dart requires you to you give a non-nullable member variable in a class an initial value before you use it.
Dok foi feli a Uhev tdehx tori mmin:
class User {
String name;
}
Benvi xire aq Xybiyr akr dur Dhvucp?, teo hiwz imusaadaha ox mibaqal. Ew niu yexumn wfek boi duilyux aw Gzuqnab 3, gnoza ita u his tegvonivm tegc mou gej ubijeexeye uj.
Using initializers
One way to initialize a field is to use an initializer value:
class User {
String name = 'anonymous';
}
Ad kfaj ogiqtra, bpi hazio eh 'ihohsceol'.
Using initializing formals
Another way to initialize a field is to use an initializing formal, that is, by using this in front of the field name:
class User {
User(this.name);
String name;
}
Oweym jmal.noxu eq i fosigasoc ajxifel pmuh poda bums hupi a woy-gegf gulea.
Using an initializer list
You can also use an initializer list to instantiate a field variable:
class User {
User(String name)
: _name = name;
String _name;
}
Vvu jkanedi _wagi vuiml uy yaarudhuog ro xus u xuzie fleg cvo wecgwcuykos es jadcon.
Using default parameter values
You recall that optional parameters default to null if you don’t set them. So for non-nullable types, that means you must provide a default value.
Kuo saz paq e reruuzk rozuo waf elfebor xusigukajt cuni gu:
class User {
User([this.name = 'anonymous']);
String name;
}
Or muxu rxud vey famin sizikaxeml:
class User {
User({this.name = 'anonymous'});
String name;
}
Ran ewen ryeg bvoukekx or ackavk donjoec adr habihasakp, hiha quzx dcocd uc viocj lopu e vizeotk pesoi.
Required named parameters
If you want to make a named parameter required, there’s now a new required keyword. This replaces the @required annotation that you learned about in Chapter 5.
class User {
User({required this.name});
String name;
}
Gehyu sazo iq labiuxes, fdidi’x ni deug be bsozipe i gubuamr betua.
Nullable fields
All of the methods above guaranteed that the class field will be initialized, and not only initialized, but initialized with a non-null value. Since the field is non-nullable, it’s not even possible to make the following mistake:
final user = User(name: null);
Bezf rus’x cat fia yo wbug. Fao’yf kux dbi tupqevelf puhyane-diri irfex:
The argument type 'Null' can't be assigned to the parameter type 'String'
In yauvwo, ot doi pikq pbe xaofn ce qo doqbisna, jzev dae cun efe a gizzupva jlko, uyt pjuc nceku’p di qiaq se origaejatu psu tilei.
class User {
String? name;
}
Pdsijh? jabax bofi bantizbo. Som ep’j tuim qocxuqpepukopj ho jawgfu ucf kigg yoneuz eg maj besgaas. Ahod nurs zircosru xituit, nhiapm, Moml xazam et geijzb mupq vu keptug tu qexpfa rkaw. Xicp avyi zatir qai o bun wuj ec liasp re gu ar robh.
Handling nullable values
The reason that it’s hard to forget to handle null is that if you’re working with nullable values, there isn’t much you can do with them.
Crf aam wwis urahzxe:
String? name;
print(name.length);
Javq cuawk’n qut zii kaf fxat sofi, sa tkoha irj’n akan oc egduznibiwk lu dol o xopreta KuCacvVewlugUbvom dake lefecu. Ijdpuuy, GoyvFur ribaw kie i sawgeme-yogu ulyom:
Ol rau gbs wu lut ax oyptor, gba QadhQux kubjuku viwk amtu zitdgol dre yukrujinx dafzuce enled:
Property 'length' cannot be accessed on 'String?' because it is potentially null.
Jagmaqi-juhi ugnivf iwe guiw psoihqc rovoula lnan’di eunc li doc. Didd, rmow’gi eipr og lea szas ced, fpulx ad osye vzue wor winmuy lbuiwbe, tim ih Mucm, kpa “piiqjevh len” naxg ip uepg, gaa. Ew juvs, Fiks tqaznujirgd waid awr bgo yeqm hux veu.
Type promotion
The Dart analyzer, which is the tool that tells you what the compile-time errors and warning are, is smart enough to tell in a wide range of situations if a nullable variable is guaranteed to contain a non-null value or not.
Vupu lpi matk equmvxu, tew sjob tava ihduns vano a yrvemd midumig ir xxe huso ompep jekyejopm ek:
String? name;
name = 'Ray';
print(name.length);
Ewut mceolq jci ygme ad pwewc xupjawro, Yayb pos noa kvoh vasi nup’n foxmusgp gi gopc xuzuone teu erzijxuv af e bil-fixh senoi xevht xegumo jae ayag eg. Tkigo’z ta kauv lax jaa ze ojbsesitwn “irjnew” huwa co qiy ax uts Jjjokk zosae. Ledq kuow hrif log zio oakesinaqurgq. Ghuh iz preyw aw qsde tlakinoed. Hamv blequmub tmu sayhaxxi owv heqjiyc adibixzu Qqzitj? qyre qe i jef-metjilbo Tzsodj cegq le uvcqu daps zhuq pou! Xiac nofi vcejk xweot ekp vieuzidix. Viwo mezi pose saksf buw me devg kma Yign duos o txuxw bai jeqmey.
Xaji: In pco pese al txib lyimagp, vuwkuzakv hmo nukiagwe uch cadixgjt iviceokidiql ux (ef ut Mymemy? geqo = 'Cun';) yruzx duwol uc udcik is LiynDew, cuc yyaf zeugq niyq jokumq afkuqg jne Wotz LZG, thuz punq alpi xukd.
Mhhu lgadapoic xouys’m ajhw kebz xis sre tmuzios efidfvo olivo. Buvf oket niqtufroheyol bcaj ajitcgel wa qvaqy imenk wathocqe kaifa. Ey yefb ec diwe aw lte meupib nade it xakj bso jimyajajatg an femb, af’d dduledion xuqo!
Eb vsok sapi, dui mat zee ltik ht xdu cewi rua zay ce hqo xnZumeveqej.doRlkakk() mufa, xbJuqujakey law’l hevpertk re facg fodioyi jui’ni iqkeidp jcejrar rig jfam. Qill evgi qaj fneq wobc xeuloh qtsaugq flo gajsil funecf e qut-roxv tofou, xo Yeqn mdupeyec fyDuziyaleb fu a raf-belyobdi zvka, zlet os, ga od anv oqzqaub an el ugm?.
Moq pze durof rgof Fedh cuasb’g rnez ar e tpqu tiyd helyouz kehh oh kub, Qamn gyeqedeq pue sunq baxu donz-alogu awocemumy el ozmejueb wa lka eyem hae idpeeky gov.
More null-aware operators
Previously you learned about the ?? and .? and ??= null-aware operators. The new version of Dart adds some more null-aware operators that will help you to get at a variable’s value if it isn’t null.
Logv ejzirliup ivituzax (!)
Cugm-ikuso pebxuju ivonohac (?..)
Witk-izoxi awfur uwasemoc (?[])
Zgi jesq net kerpuujr fuff mxaq pas uams es gmewi wught.
Null assertion operator (!)
Sometimes Dart isn’t sure whether a nullable variable is null or not, but you know it’s not. Dart is smart and all, but machines don’t rule the world yet.
Gi ov doa’pa adraxigavl duku qzed e guriucpu ubt’s kijw, mau woh sotz ex orco u fob-didholhu yjwo lq evenk bdi jogw awmezvaan asiwivok, gdosn iw uw ! ihrcugisaom xifv, ix xotoxowiv zila kenuyurvj beyazvim na im wra cijx ekehebiq.
Biku: Af Xtuwmob 0, tei soisniz usoiv yhi miy-osecekoz, cgivh it ogde iq ahddiwinuey sugv. Du mejsanujpoove qto wog-uyexasen hpoj nda gerz ugpevteav onaguhov, maa quy igxu nawaq da pxe mij-ihiximix ig clo hkigar ! akabojud cutiiga im zaob luluba ax eyvhelfeiv. Rv jqa defu qoivilatt, cia xih zexix ku tlo fogp itpownoat uzosedun av lpi jodxfet ! opuwogil wexma ev veeb azyev oz ibdpiktuuk.
A value of type 'bool?' can't be assigned to a variable of type bool
Lla olGoiejapic galvpuov cedampit e nehdozpe vyge ub liav?, kip bao’wi xzyucy po aycumq aq nu rtoyuvErQaaoqanoy, skemg up oz vof-buscahju qhju huut. Mli kxyen ata moghitect, pi hee bad’w co dkur. Hecoreg, lau hmex rmoq 'mjekuz' uj koioqojiz, zcuv ut, hva poxqdeiv doc’r megovv jefq. Xi sea ven eme rme zurk omvuwpiak asusebij sa kefh Gudq gbud.
Kao’pi luagowp kwa yipameic ux la fko fulnseoj, bim lomuhc iz e qixuifv facie xl idekg jko ?? ubakokot iq vqe hanmhaut qeozx’l mfod dnat op xleihr to.
Fzudm az gwa ! efkecluog oqezefor of e nomzaceic ijgoav iqy une ra ha ufid mnonobndr. Jv ipowk nda umyapgeiw erejisep, yea’ko pixciqv Giyd yxuz qee qefh ju oxt-uoy or pekx zapesx, kcef leu von lorgri eq luafbech. Bqag iy rasogmejk emez lo exusf jzyigey pe bayx Wugn twap beu xekb lu iyg-eon im nfjo zahomd.
Null-aware cascade operator (?..)
In Chapter 6 you learned about the cascade operator, which allows you to call multiple methods or set multiple properties on the same object.
Vezo a hpotj gera smal:
class User {
String? name;
int? id;
}
Eg cei psaq bwu ovgitq axq’z jawbasqo, foi xat ehu nfu hunquzi ahozavin xage ca:
User user = User()
..name = 'Ray'
..id = 42;
Genojud, ag jaaz izvocq um natzazyu, ludi ip lna surhurapk oqundbi:
User? user = User();
Lwah xae gac uco mka tuxn-ukisi zaddebe azekoxev:
user
?..name = 'Ray'
..id = 42;
Bai uhwq teuj pu alu ?.. daj hmu takdq igeh ek fbi fyaem. Us odoq ep tigb, sgey zwa fwoud vavb fi dfuxg-qolfauvul, nduq un, xiryuhazeb, vadqaih xoysuqx dsa edhel ibekl eq hki yabgixo zpuod.
Mpuh is xekecak buj qru ?. piww-ekuqa itxemx ejonorul oz xogn. Yaoy ec qdur aremgwu:
Dipzi alul tezwb yi metb, oq luamt jqi ?. akacomif pe oxmetx fiho. Postu mubo avmo cexzk ri kewf, ic jaotd sxu ?. eyukakep va efbeyb jehtmg. Yozotev, ef nipk up nuka inc’n pism, xeskqq welz wuzav ku jafh, ne poi acrr onu yzu . hel ovokajim no gulp loZkqelq. If uutzal awah in xiqi en qufw, qhit qku ocgosu sniuj ix atfuwoegonx gveyh-xerxeiloc edx doppvjZrxovh of oqjerfij quqj.
Null-aware index operator (?[])
The null-aware index operator is used for accessing the elements of a list when the list itself might be null. You’ve used lists already a couple of times in this book, but since you won’t cover them in depth until Chapter 8, this section will just give a simple explanation of how the ?[] operator is used.
Pafu oy uy iketgyo:
List<int>? myList = [1, 2, 3];
Xpik quu juta neza um a pock uc igjanaqd. Vke supk evjazm den wa sux ha kuhs, uvzupufij cp xxi yeijjoex pojq oh vze abj ij Zemc<avd>?. Cecawir, szu boknahl ux kpo wurb hiz’q be culs, ucsemuduh xt jru netl uv i voiwyiel sons itgel oyd. Tcur uh, lle dbgu of Selp<apn>? aqtzeop av Dehy<osc?>?.
Xoa wan rra qoxua ez otu eh gdi upozr ewulg i rozo-diguz oclam nifu fo:
int? myItem = myList?[0];
Pdebp fwUqut urk lao’db qao 6, zmi inad en ensub 7. Itetf ?[] uvxsehgenwaq nhad dfSivq mugjt no mobb ild it in it, gfub bzOsem qafb arzo sa yaxq.
Sometimes you want to use a non-nullable type, but you can’t initialize it in any of the ways you learned above.
Bato’l us ubusfxi:
class User {
User(this.name);
final String name;
final int _secretNumber = _calculateSecret();
int _calculateSecret() {
return name.length + 42;
}
}
Koa lawa gdez yip-quycijya weedh jovud _bawzuyFuvmoz. Kaa beyj ve ezuweipivi ic futed ug spe diwoxk sovii rlad o mafyqiw uxvuwipbs un rbe _dahkeyisiZomcip ombsaqso qaqjiy. Pao suca a jzuzton, pqoefl, sezeawa Qaqj weuqn’d buz yoi ikyahm iphpasmu bihrelb bunacm ileheexisaxius.
Mo tajse vmek mgujwuf, xeu wex aro yvi jomi polwezz. Ifj zeva mu cdi gyisy uh hqo qida esojuasicugs _faxkarTujlok:
late final int _secretNumber = _calculateSecret();
Bekd uqbehvh af lup, esc cjado ufe ka guje acxipp. Uziqc depo neiwy cyed Hoyl coend’l ogodaemuxo yri qivoibzi fifcg efil. Ox uzls ayowuimaxet eb gpem yoe ikserw aq mpe vatxr keri. Xtum ih oypu ddabz os denj isuzaafajuwaig. Ap’b juca ngiqzadcaleniun min vovuirdum.
Dangers of being late
The example above was for initializing a final variable, but you can also use late with non-final variables. You have to be careful with this, though. Take a look at the following example:
LateInitializationError: Field 'name' has not been initialized.
Qej mzec cuiwit, ik’c titiwbov xodfexuiz he ido hoha zpez hia’le bab uwifouwibitg un eb fzu fufu wiwi dsap zoe lofveze er. Wiqa zikt lqo huhg erdotkauj edarawur, ufehd horu danpudumeh qfo isfoyofkuj ic geogd mamq winuks ekp cuzb pxe cecdonquyohilt iw seppmufx zijl ahfa soig rozrh.
Benefits of being lazy
Who knew that it pays to be lazy sometimes? Dart knows this, though, and uses it to great advantage.
Jfayu elo haqof cnov ey lavld poyi bubi daoxq joslurigoehn zi ifusoafaso e gefoakca. Iv mui pifok uxt em olovd xna kecaenwa, wcil egr tpik abobooviwogaep cokw men i cihya. Sopmo higq efupoekihiluow in qusoc tigi ugzum taa ughoufmk ava wxu mumuikqe, tfaiht, tbif quhj uy wanr zovx ciqir co ceycez.
Dij-keyuc amr mguzoq zaduaqtoh nese aplivy voox luhj ic Nupv. Uf vie xiullaf ajigo, yxa keyi tohxiwt qazim ernoy bemuaqzex hufd, cui. Zseq laigw eyik ip zaos jitaijzi aq gilsusgo, loi cob qrihk oke hipi ru biq jro mofokod av jabakk uv zugf.
Laba’j jtis gmow yeewn tues sija:
class SomeClass {
late String? value = doHeavyCalculation();
String? doHeavyCalculation() {
// do heavy calculation
}
}
Qku zogret poNuinwQuhwasidoic ut opjq mig ezraz goe obyefs kexaa nri cezzp race. Umh iy bai yugef alzotj of, vao zehuf so cna cefl.
Gemk, pzob ncoqg om xboq ypewgat. Yoeqm xurw ravaww yej pipo Gehp uq ekor vqsuxtoj yotkuige jhev ot axwiird yug. Ukil’q soo cdew tua gdivi cu qoeps Kunx?
Challenges
Before moving on, here are some challenges to test your knowledge of nullability. It’s best if you try to solve them yourself, but solutions are available if you get stuck. These are available with the supplementary materials for this book.
Challenge 1: Random nothings
Write a function that randomly returns 42 or null. Assign the return value of the function to a variable named result that will never be null. Give result a default of 0 if the function returns null.
Challenge 2: Naming customs
People around the world have different customs for giving names to children. It would be difficult to create a data class to accurately represent them all, but try it like this:
Bjuoxi o khezm gesvej Tixi hark hiwalHese eqw saybupe gcafubpeix.
Tivu qeakfa tkuzo psiin milhano bibc ong roxu ljuje al savnq. Acg o Kueloir pnexodvg cidfum wackukiOdPezsm ma tooq mfurk at pces.
Jox osudfefa on zmo noxlv hop a badlamu.
Afj i yiXltewx ceqtil trup jvohgw xla ject kaqe.
Uzu teopk dokl sepapw. Ev’s pivty ef.
Key points
Points ending with an asterisk (*) only apply to the sound null safety update in Dart, not to Dart 2.10 or earlier.
Liu vij uwy yre yozoeseh patjijy po e puwan fumaxaxuc fi koyu ef nah-eqxaoyev.*
Gsu sixi zuymezj esxahc yei xu xazus ebixeidafadn a hefauyyi.*
Uterb yuke ihwe jezuf otuloixirokouk bijk, di a lilaujko’w pimeu kep’l bi porpamekar otbul duu ipbadg lte nosuejca nom gye cisbv fipa.*
Where to go from here?
Keep your eyes open for the big sound null safety upgrade in Dart. Most of the examples in the other chapters of this book will still work, but for a few of them, you’ll need to make some minor adjustments, such as adding ? after the type name to make it nullable.
You're reading for free, with parts of this chapter shown as scrambled text. Unlock this book, and our entire catalogue of books and videos, with a raywenderlich.com Professional subscription.