Dart vs Swift: samanburður

Dart-merkið er með leyfi samkvæmt Creative Commons Attribution 3.0 Unported leyfinu.

Dart og Swift eru tvö uppáhalds forritunarmálin mín. Ég hef notað þær mikið í viðskiptalegum og opnum kóða.

Þessi grein býður saman hlið við hlið milli Dart og Swift og miðar að:

  • Auðkenndu muninn á þessu tvennu.
  • Vertu tilvísun fyrir forritara sem fara frá einu tungumáli yfir á annað (eða nota bæði).

Nokkuð samhengi:

  • Dart valdir Flutter, ramma Google til að byggja falleg innfædd forrit úr einum kóðabasis.
  • Swift vald SDKs Apple yfir iOS, macOS, tvOS og watchOS.

Eftirfarandi samanburður er gerður á helstu eiginleikum beggja tungumálanna (frá Dart 2.1 og Swift 4.2). Þar sem fjallað er ítarlega um hverja aðgerð er umfang þessarar greinar, læt ég fylgja með tilvísanir til frekari lesturs þar sem það á við.

Efnisyfirlit

  • Samanburðartafla
  • Breytur
  • Gerðu ályktun
  • Breytanlegar / óbreytanlegar breytur
  • Aðgerðir
  • Nefndu og ónefndu færibreytur
  • Valfrjáls og sjálfgefin breytur
  • Lokanir
  • Tuples
  • Stjórna flæði
  • Söfn (fylki, sett, kort)
  • Nullability & Optionals
  • Flokkar
  • Erfðir
  • Fasteignir
  • Bókanir / ágripstímar
  • Mixins
  • Viðbyggingar
  • Enums
  • Mannvirki
  • Villa við meðhöndlun
  • Generics
  • Aðgangsstýring
  • Ósamstilltur forritun: Framtíðir
  • Ósamstilltur forritun: Straumar
  • Minni stjórnun
  • Samantekt og framkvæmd
  • Aðrir eiginleikar ekki fjallað
  • Uppáhalds Swift aðgerðir mínar vantar í Dart
  • Uppáhalds Dart aðgerðir mínar vantar í Swift
  • Niðurstaða
  • Tilvísanir

Samanburðarborð

Breytur

Breytileg yfirlýsing um yfirlýsingu lítur svona út í Dart:

Streng nafn;
aldur;
tvöföld hæð;

Og svona í Swift:

var nafn: String
var aldur: Int
var hæð: Tvöfalt

Breytileg frumstilling lítur svona út í Dart:

var nafn = 'Andrea';
var aldur = 34;
var hæð = 1,84;

Og svona í Swift:

var nafn = "Andrea"
var aldur = 34
var hæð = 1,84

Í þessu dæmi er ekki þörf á athugasemdum. Þetta er vegna þess að bæði tungumálin geta ályktað um gerðirnar frá tjáningunni hægra megin við verkefnið.

Talandi um…

Gerðu ályktun

Gerð ályktunar þýðir að við getum skrifað eftirfarandi í Dart:

var rök = {'argA': 'halló', 'argB': 42}; // Kort 

Og gerð rökanna er sjálfkrafa leyst af þýðandanum.

Í Swift er hægt að skrifa það sama og:

var argumente = ["argA": "halló", "argB": 42] // [Strengur: Allir]

Nokkrar frekari upplýsingar

Tilvitnun í skjölin fyrir Dart:

Greiningartækið getur ályktað um gerðir fyrir reiti, aðferðir, staðbundnar breytur og flestar almennar tegundarrök. Þegar greiningartækið hefur ekki nægar upplýsingar til að álykta um tiltekna gerð notar hann kraftmikla gerð.

Og fyrir Swift:

Swift notar gerðir ályktana mikið, sem gerir þér kleift að sleppa gerð eða hluta af gerðinni af mörgum breytum og orðasamböndum í kóðanum þínum. Til dæmis, í stað þess að skrifa var x: Int = 0, geturðu skrifað var x = 0 og sleppt gerðinni alveg - þýðandinn bætir rétt inn sem x nefnir gildi af gerðinni Int.

Dynamic gerðir

Breytileiki sem getur verið af hvaða gerð sem er er lýst með kraftmiklu leitarorði í Dart og hvaða lykilorð sem er í Swift.

Dínamískar gerðir eru oft notaðar við lestur gagna á borð við JSON.

Breytanlegar / óbreytanlegar breytur

Hægt er að lýsa breytum sem breytanlegar eða óbreytanlegar.

Til að lýsa yfir breytanlegum breytum nota bæði tungumálin lykilorðið.

var a = 10; // int (píla)
a = 20; // allt í lagi
var a = 10 // Int (Swift)
a = 20 // allt í lagi

Til að lýsa yfir óbreytanlegum breytum, notar Dart endanlega og Swift notar let.

loka a = 10;
a = 20; // 'a': lokabreytu, aðeins hægt að stilla einu sinni.
látum a = 10
a = 20 // Get ekki úthlutað gildi: 'a' er stöðugt 'láta'

Athugasemd: Dart skjölin skilgreina tvö lykilorð, endanleg og const, sem virka sem hér segir:

Ef þú ætlar aldrei að breyta breytu skaltu nota final eða const, hvorki í staðinn fyrir var eða í viðbót við gerð. Hægt er að stilla lokabreytu aðeins einu sinni; const breytu er samantekt tíma stöðug. (Const breytur eru óbeint endanlegar.) Endanleg efsta stig eða bekk breytu er frumstilla í fyrsta skipti sem hún er notuð.

Nánari skýringar er að finna á þessari færslu á Dart vefsíðunni:

loka þýðir eins verkefni. Lokabreytileiki eða reitur verður að hafa frumstillingu. Þegar gildi hefur verið úthlutað er ekki hægt að breyta gildi lokabreytu. final breytir breytum.

TL; DR: notaðu final til að skilgreina óbreytanlegar breytur í pílu.

Í Swift lýsum við fastmönnum með látum. Tilvitnun:

Stöðug yfirlýsing kynnir stöðugt nafngildi í forritið þitt. Stöðug yfirlýsingar eru lýst yfir með því að nota lykilorð og hafa eftirfarandi form:
láta stöðugt nafn: tegund = tjáning
Stöðug yfirlýsing skilgreinir óbreytanlega bindingu milli föstu nafns og gildi upphafstjáningarinnar; eftir að gildi föstunnar er stillt er ekki hægt að breyta því.

Lestu meira: Skjótar yfirlýsingar.

Aðgerðir

Aðgerðir eru fyrsta flokks borgarar í Swift og Dart.

Þetta þýðir að rétt eins og hlutir, þá er hægt að færa aðgerðir sem rök, vista sem eiginleika eða skila þeim í kjölfarið.

Sem fyrstu samanburður getum við séð hvernig á að lýsa yfir aðgerðum sem taka engin rök.

Í Dart er afturgerðin á undan aðferðarheiti:

ógilt foo ();
int bar ();

Í Swift notum við merkinguna -> T sem viðskeyti. Þetta er ekki krafist ef það er ekkert skilagildi (ógilt):

func foo ()
func bar () -> Int

Lestu meira:

  • Píluaðgerðir
  • Snöggar aðgerðir

Nefndu og ónefndu færibreytur

Bæði tungumál styðja nafngreinda og ónefnda breytur.

Í Swift eru breytur sjálfgefnar nefndar:

func foo (nafn: String, aldur: Int, hæð: tvöfalt)
foo (nafn: "Andrea", aldur: 34, hæð: 1,84)

Í Dart skilgreinum við nefndar færibreytur með hrokkið axlabönd ({}):

ógilt foo ({strengjaheiti, aldur, tvöfaldur hæð});
foo (nafn: 'Andrea', aldur: 34, hæð: 1,84);

Í Swift skilgreinum við ónefndar breytur með því að nota undirstrik (_) sem utanaðkomandi breytu:

func foo (_ nafn: strengur, _ aldur: milliliður, _ hæð: tvöfalt)
foo („Andrea“, 34, 1,84)

Í Dart skilgreinum við ónefndar færibreytur með því að sleppa hrokkið axlaböndunum ({}):

ógilt foo (strengjaheiti, aldur, tvöfaldur hæð);
foo ('Andrea', 34, 1,84);

Lestu meira: Virkni rifrildamerki og nöfn breytu í Swift.

Valfrjáls og sjálfgefin breytur

Bæði tungumál styðja sjálfgefna breytur.

Í Swift geturðu skilgreint sjálfgefið gildi fyrir hvaða færibreytu sem er í aðgerð með því að tengja gildi við færibreytuna eftir gerð þeirrar breytu. Ef sjálfgefið gildi er skilgreint er hægt að sleppa þeim færibreytum þegar hringt er í aðgerðina.
func foo (nafn: Strengur, aldur: Int = 0, hæð: Tvöfalt = 0,0)
foo (nafn: "Andrea", aldur: 34) // nafn: "Andrea", aldur: 34, hæð: 0,0

Lestu meira: Sjálfgefin breytur gildi í Swift.

Í Dart geta valfrjálsir færibreytur verið annað hvort staðsetningar eða nafngreindir, en ekki báðir.

// staðalfrjálsar breytur
ógilt foo (strengjaheiti, [aldur = 0, tvöföld hæð = 0,0]);
foo ('Andrea', 34); // nafn: 'Andrea', aldur: 34, hæð: 0,0
// nefnt valfrjáls breytur
ógilt foo ({Strengheiti, aldur = 0, tvöföld hæð = 0,0});
foo (nafn: 'Andrea', aldur: 34); // nafn: 'Andrea', aldur: 34, hæð: 0,0

Lestu meira: Valfrjáls færibreytur í Dart.

Lokanir

Að vera fyrsta flokks hlutir, aðgerðir geta komið fram sem rök fyrir öðrum aðgerðum, eða þeim falið breytur.

Í þessu samhengi eru aðgerðir einnig þekktar sem lokanir.

Hér er Dart dæmi um aðgerð sem endurtekur yfir lista yfir hluti og notar lokun til að prenta vísitölu og innihald hvers hlutar:

lokalisti = ['epli', 'bananar', 'appelsínur'];
list.forEach ((item) => prenta ('$ {list.indexOf (item)}: $ item'));

Lokunin tekur ein rök (hlut), prentar vísitölu og gildi þess hlutar og skilar engu gildi.

Athugaðu notkun örmerkisins (=>). Þetta er hægt að nota í stað eins skilatilkynningar innan hrokkið axlabönd:

list.forEach ((hlutur) {prenta ('$ {list.indexOf (hlutur)}: $ hlutur');});

Sami kóði í Swift lítur svona út:

láta lista = ["epli", "bananar", "appelsínur"]
list.forEach ({prenta ("\ (strengur (lýsir: list.firstIndex (af: $ 0))) \ ($ 0)")})

Í þessu tilfelli tilgreinum við ekki nafn fyrir röksemdafærsluna sem færð var til lokunar og notum $ 0 í staðinn til að meina fyrstu rökin. Þetta er alveg valfrjálst og við getum notað nafngreinda breytu ef við viljum:

list.forEach ({hlutur á prenti ("\ (strengur (lýsir: list.firstIndex (af: hlut))) \ (hlutur)")})

Lokanir eru oft notaðar sem lokaraðir fyrir ósamstilltur kóða í Swift (sjá kafla hér að neðan um ósamstilltur forritun).

Lestu meira:

  • Dart nafnlaus aðgerðir
  • Snöggar lokanir

Tuples

Úr skjótum skjölum:

Tuples hópa mörg gildi í eitt samsett gildi. Gildin innan túpunnar geta verið af öllum gerðum og þurfa ekki að vera af sömu gerð og hvert annað.

Hægt er að nota þær sem litlar léttar gerðir og eru gagnlegar þegar skilgreint er aðgerðir með margfeldi skilagilda.

Hérna er hvernig á að nota bólur í Swift:

láta t = („Andrea“, 34, 1,84)
prenta (t.0) // prentar „Andrea“
prenta (t.1) // prentun 34
prenta (t.2) // prentar 1,84

Tuples eru studd með sérstökum pakka í Dart:

const t = const Tuple3  ('Andrea', 34, 1,84);
prenta (t.item1); // prentar 'Andrea'
prenta (t.item2); // prentar 34
prenta (t.item3); // prentar 1,84

Stjórna flæði

Bæði tungumál bjóða upp á margvíslegar yfirlýsingar um stjórnunarflæði.

Dæmi um þetta eru ef skilyrðingar, fyrir og meðan lykkjur, skipta yfirlýsingum.

Það væri nokkuð langt að fjalla um þetta hér, svo ég vísa til opinberu skjalanna:

  • Snöggt stjórnunarflæði
  • Yfirlýsingu um rennsli um pílu

Söfn (fylki, sett, kort)

Fylki / Listar

Fylki eru skipaðir hópar af hlutum.

Hægt er að búa til fylki sem listar í pílu:

var emptyList =  []; // tómur listi
var listi = [1, 2, 3]; // lista bókstaflega
list.length; // 3
listi [1]; // 2

Fylki eru með innbyggða gerð í Swift:

var tómt Fylki = [Int] () // tóm fylking
var fylki = [1, 2, 3] // fylki bókstaflega
array.count // 3
fylki [1] // 2

Leikmynd

Vitna í skjótt skjal:

Leikmynd geymir sérstök gildi af sömu gerð í safni án skilgreindrar röðunar. Þú getur notað sett í staðinn fyrir fylki þegar röð hlutanna er ekki mikilvæg, eða þegar þú þarft að sjá til þess að hlutur birtist aðeins einu sinni.

Þetta er skilgreint með Set bekknum í Dart.

var tómFruits =  {}; // tómur setja bókstaflegur
var ávextir = {'epli', 'banani'}; // setja bókstaflega

Sömuleiðis í Swift:

var emptyFruits = Stilltu  ()
var ávextir = Settu  (["epli", "banani"])

Kort / orðabækur

Swift skjölin hafa góða skilgreiningu á korti / orðabók:

Orðabók geymir tengsl milli lykla af sömu gerð og gildum af sömu gerð í safni án skilgreindrar röðunar. Hvert gildi er tengt við sérstakan lykil sem virkar sem auðkenni fyrir það gildi í orðabókinni.

Kort eru skilgreind eins og í Dart:

var namesOfIntegers = Kort  (); // tómt kort
var flugvellir = {'YYZ': 'Toronto Pearson', 'DUB': 'Dublin'}; // kort bókstaflega

Kort kallast orðabækur í Swift:

var namesOfIntegers = [Int: String] () // tóm orðabók
var flugvellir = ["YYZ": "Toronto Pearson", "DUB": "Dublin"] // orðabók bókstaflega

Lestu meira:

  • Píla söfn
  • Snöggar söfn (sérstaklega mæli ég með hlutanum um sett).

Nullability & Optionals

Í Dart getur hver hlutur verið null. Og að reyna að fá aðgang að aðferðum eða breytum af núll hlutum leiðir til undantekningar á núllmerki. Þetta er ein algengasta villan (ef ekki sú algengasta) í tölvuforritum.

Frá upphafi átti Swift valkosti, innbyggður tungumálatækni til að lýsa því yfir hvort hlutir geta eða geta ekki haft gildi. Að vitna í skjölin:

Þú notar valkosti við aðstæður þar sem gildi getur verið fjarverandi. Valfrjálst táknar tvo möguleika: Annaðhvort er gildi, og þú getur tekið valfrjálsan aðgang upp til að fá aðgang að gildinu, eða það er alls ekki gildi.

Öfugt við þetta getum við notað breytur sem ekki eru valkvæðar til að tryggja að þær muni alltaf hafa gildi:

var x: Int? // valfrjálst
var y: Int = 1 // ekki valfrjálst, verður að frumstilla

Athugasemd: Að segja að Swift-breytu sé valkvæð er nokkurn veginn það sama og að segja að Dart-breytu geti verið null.

Án stuðnings á tungumálastigi fyrir valkosti getum við aðeins athugað á afturkreistingum hvort breytan er núll.

Með valkostum, umrita við þessar upplýsingar í samsetningu tíma. Við getum losað um valkosti til að kanna á öruggan hátt hvort þeir hafi gildi:

func sýningVal (x: Int?) {
  // notaðu `varnarleyfi` frekar en` ef látið` sem bestu starfshætti
  ef láta x = x {// taka upp valfrjálst
    prenta (x)
  } Annar {
    prenta („ekkert gildi“)
  }
}
showOptional (x: nil) // prentar „ekkert gildi“
showOptional (x: 5) // prentar „5“

Og ef við vitum að breytu verður að hafa gildi, getum við notað valfrjálst:

func showNonOptional (x: Int) {
  prenta (x)
}
showNonOptional (x: nil) // [compile error] Nil er ekki samhæft við væntanleg rök tegund 'Int'
showNonOptional (x: 5) // prentar „5“

Fyrsta dæmið hér að ofan er hægt að útfæra svona í Dart:

ógilt sýningVal (int x) {
  ef (x! = null) {
    prenta (x);
  } Annar {
    prenta ('ekkert gildi');
  }
}
showOptional (null) // prentar „ekkert gildi“
showOptional (5) // prentar „5“

Og sú síðari svona:

ógilt showNonOptional (int x) {
  fullyrða (x! = núll);
  prenta (x);
}
showNonOptional (null) // [runtime error] Undanskilin undantekning: fullyrðing mistókst
showNonOptional (5) // prentar "5"

Að hafa valkosti þýðir að við getum lent í villum á samantektartíma frekar en á hlaupum. Og smitandi villur skilar snemma öruggari kóða með færri galla.

Skortur á stuðningi Dart við valkosti er á einhvern hátt mildaður með því að nota fullyrðingar (og @ krafist umsagnar um nafngreinda stika).

Þetta er mikið notað í Flutter SDK en hefur í för með sér viðbótarkóða ketils.

Fyrir the skrá, það er tillaga um að bæta ekki nullable tegundir við Dart.

Það er miklu meira um valkosti en ég hef fjallað um hér. Fyrir gott yfirlit, sjá: Valkostir í Swift.

Flokkar

Námskeið eru aðalbyggingin fyrir að skrifa forrit á hlutbundnum tungumálum.

Námskeiðin eru studd af Dart og Swift, með nokkrum mismun.

Setningafræði

Hér er flokkur með frumstillingu og þremur meðlimabreytum í Swift:

bekkjarpersóna {
  láta nafn: String
  láta aldur: Int
  láta hæð: Tvöfalt
  init (nafn: Strengur, aldur: Int, hæð: tvöfalt) {
    self.name = nafn
    sjálf.age = aldur
    self.height = hæð
  }
}

Og það sama í Dart:

bekkjarpersóna {
  Persóna ({þetta.heiti, þetta.age, þetta.hæð});
  endanlegt String nafn;
  endanleg aldur;
  endanleg tvöföld hæð;
}

Athugið notkun þessa. [PropertyName] í Dart-smiðjunni. Þetta er setningafræðilegur sykur til að stilla tilviksaðildarbreytur áður en framkvæmdaaðilinn keyrir.

Framkvæmdir við verksmiðjuna

Í Dart er mögulegt að búa til verksmiðjubyggingar. Tilvitnun:

Notaðu verksmiðjuorðið þegar þú framkvæmir smíði sem býr ekki alltaf til nýtt tilvik í sínum flokki.

Eitt raunhæft tilfelli smiðja verksmiðjunnar er þegar þú býrð til fyrirmyndarflokk frá JSON:

bekkjarpersóna {
  Persóna ({this.name, this.age, this.height});
  endanlegt String nafn;
  endanleg aldur;
  endanleg tvöföld hæð;
  verksmiðju Person.fromJSON (Map  json) {
    String name = json ['name'];
    int age = json ['age'];
    tvöfaldur hæð = json ['hæð'];
    skila Persónu (nafn: nafn, aldur: aldur, hæð: hæð);
  }
}
var p = Person.fráJSON ({
  'nafn': 'Andrea',
  'aldur': 34,
  'hæð': 1,84,
});

Lestu meira:

  • Pílaflokkar
  • Snöggar mannvirki og flokkar

Erfðir

Swift notar eins arf líkan, sem þýðir að hver flokkur getur aðeins haft einn ofurflokk. Swift flokkar geta innleitt mörg tengi (einnig þekkt sem samskiptareglur).

Pílaflokkar hafa arfleifð sem byggir á mixin. Að vitna í skjölin:

Sérhver hlutur er dæmi um flokk og allir flokkar stíga niður af hlutnum. Arf sem byggir á mixin þýðir að þó að sérhver flokkur (nema hlutur) hafi nákvæmlega einn ofurflokk, þá er hægt að endurnýta flokks líkama í mörgum stigveldum.

Hérna er einn arfur í aðgerð í Swift:

farartæki {
  láta WheelCount: Int
  init (WheelCount: Int) {
    self.wheelCount = WheelCount
  }
}
bekk hjólandi: farartæki {
  í því() {
    super.init (hjólatölu: 2)
  }
}

Og í Dart:

farartæki {
  Ökutæki ({this.wheelCount});
  endanleg int hjólFjárhæð;
}
bekk Hjól framlengir ökutæki {
  Reiðhjól (): frábær (hjólatölu: 2);
}

Fasteignir

Þetta eru kallaðar dæmi breytur í Dart og einfaldlega eiginleikar í Swift.

Í Swift er gerður greinarmunur á geymdum og reiknuðum eiginleikum:

bekkjarhringur {
  init (radíus: tvöfalt) {
    self.radius = radíus
  }
  láta radíus: tvöfaldur // geymd eign
  var þvermál: Tvöfaldur {// tölvueiginleiki skrifvarnar
    aftur radíus * 2,0
  }
}

Í Dart erum við með sama greinarmun:

bekkjarhringur {
  Hringur ({this.radius});
  endanlegur tvöfaldur radíus; // geymdar eignir
  tvöfaldur fá þvermál => radíus * 2,0; // reiknuð eign
}

Auk getters fyrir reiknaða eiginleika getum við einnig skilgreint setjara.

Með því að nota dæmið hér að ofan getum við skrifað um þvermálseiginleika til að innihalda setjara:

var þvermál: tvöfaldur {// reiknuð eign
  fá {
    aftur radíus * 2,0
  }
  setja {
    radíus = newValue / 2.0
  }
}

Í Dart getum við bætt við sérstökum settara eins og svo:

stilla þvermál (tvöfalt gildi) => radíus = gildi / 2,0;

Fasteignasalar

Þetta er sérkennileg einkenni Swift. Tilvitnun:

Fasteignaeftirlitsmenn fylgjast með og svara breytingum á verðmæti eignarinnar. Fasteignaeftirlitsmenn eru kallaðir í hvert skipti sem verðmæti eignar er stillt, jafnvel þó að nýja verðmætið sé það sama og núverandi verðmæti eignarinnar.

Svona er hægt að nota þau:

var þvermál: Tvöfaldur {// tölvueiginleiki skrifvarnar
  willSet (newDiameter) {
    prenta ("gamalt gildi: \ (þvermál), nýtt gildi: \ (newDiameter)")
  }
  setti {
    prenta ("gamalt gildi: \ (oldValue), nýtt gildi: \ (þvermál)")
  }
}

Lestu meira:

  • Píludæmi breytur, stafir og setur
  • Snöggir eiginleikar

Bókanir / ágripstímar

Hér erum við að tala um smíði sem notuð er til að skilgreina aðferðir og eiginleika, án þess að tilgreina hvernig þeim er hrint í framkvæmd. Þetta er þekkt sem viðmót á öðrum tungumálum.

Í Swift eru tengi kölluð samskiptareglur.

siðareglur Lögun {
  func svæði () -> Tvöfalt
}
bekkjartorg: Form {
  látum: tvöfalt
  init (hlið: tvöfalt) {
    sjálf.hlið = hlið
  }
  func svæði () -> Tvöfaldur {
    snúa hlið * hlið
  }
}

Dart er með svipað smíð og þekkt er abstrakt flokkur. Ekki er hægt að koma á ágripstímum. Þeir geta þó skilgreint aðferðir sem hafa framkvæmd.

Dæmið hér að ofan er hægt að skrifa svona í Dart:

abstrakt bekkjarform {
  tvöfalt svæði ();
}
bekkjartorg lengir form {
  Ferningur ({this.side});
  endanleg tvöföld hlið;
  tvöfalt svæði () => hlið * hlið;
}

Lestu meira:

  • Skjótar siðareglur
  • Dart ágripstímar

Mixins

Í Dart er mixin bara venjulegur flokkur, sem hægt er að endurnýta í mörgum stigveldum.

Hérna er hvernig við gætum lengt Persónu bekkinn sem við skilgreindum áður með NameExtension mixin:

abstrakt bekknum NameExtension {
  Streng fá nafn;
  Strengur fá hástafanafn => nafn.tilUpperCase ();
  Strengur fá lágstafiName>> name.toLowerCase ();
}
bekk Einstaklingur með NameExtension {
  Persóna ({þetta.heiti, þetta.age, þetta.hæð});
  endanlegt String nafn;
  endanleg aldur;
  endanleg tvöföld hæð;
}
var person = Persóna (nafn: 'Andrea', aldur: 34, hæð: 1,84);
prenta (person.uppercaseName); // 'ANDREA'

Lestu meira: Dart Mixins

Viðbyggingar

Viðbætur eru hluti af Swift tungumálinu. Að vitna í skjölin:

Viðbætur bæta nýrri virkni við núverandi tegund, uppbyggingu, upptalningu eða samskiptareglur. Þetta felur í sér möguleika á að lengja gerðir sem þú hefur ekki aðgang að upprunalegu frumkóðanum (þekktur sem afturvirk líkan).

Þetta er ekki mögulegt með mixins í Dart.

Með því að lána dæmið hér að ofan getum við framlengt Persónuflokkinn þannig:

eftirnafn Persónu {
  var hástafinnafn: strengur {
    return name.uppercased ()
  }
  var lágstafir: Streng {
    skila nafn.lowercased ()
  }
}
var manneskja = Persóna (nafn: „Andrea“, aldur: 34, hæð: 1,84)
prenta (person.uppercaseName) // "ANDREA"

Það er miklu meira viðbætur en ég hef kynnt hér, sérstaklega þegar þær eru notaðar í samskiptum við samskiptareglur og samheitalyf.

Eitt mjög algengt tilfelli fyrir viðbætur er að bæta samræmi við samskiptareglur við núverandi gerðir. Til dæmis getum við notað viðbót til að bæta möguleika á raðmyndun í núverandi líkanaflokk.

Lestu meira: Swift Extensions

Enums

Dart hefur mjög grunnstoð fyrir enums.

Enums í Swift eru mjög öflug vegna þess að þau styðja tilheyrandi gerðir:

enum NetworkResponse {
  mál velgengni (líkami: Gögn)
  tilfelli bilun (villa: Villa)
}

Þetta gerir það mögulegt að skrifa rökfræði svona:

skipta (svar) {
  mál. árangur (láttu gögn):
    // gera eitthvað með (ekki valfrjáls) gögn
  tilfelli. bilun (láttu villu):
    // gera eitthvað með (ekki valfrjálst) villu
}

Athugaðu hvernig gögnin og villubreyturnar eru innbyrðis útilokuð.

Í Dart getum við ekki tengt viðbótargildi við enums og kóðinn hér að ofan gæti verið útfærður á þessa leið:

bekk netviðbragða {
  NetworkResponse ({this.data, this.error})
  // fullyrðing um að gera gögn og villur gagnkvæmar
  : fullyrða (gögn! = null && villa == null || gögn == null && villa! = null);
  endanleg Uint8List gögn;
  endanleg strengjavilla;
}
var svar = NetworkResponse (gögn: Uint8List (0), villa: null);
ef (svar.data! = null) {
  // nota gögn
} Annar {
  // nota villu
}

Nokkur athugasemdir:

  • Hér notum við fullyrðingar til að bæta upp þá staðreynd að við höfum ekki valkosti.
  • Þýðandinn getur ekki hjálpað okkur að athuga hvort öll möguleg tilvik séu til. Þetta er vegna þess að við notum ekki rofa til að vinna úr viðbrögðum.

Í stuttu máli eru Swift enums mun öflugri og svipmikill en í Dart.

Bókasöfn þriðja aðila eins og Dart Seals Unions bjóða svipaða virkni og það sem í boði er hjá Swift enums og getur hjálpað til við að fylla skarðið.

Lestu meira: Swift Enums.

Mannvirki

Í Swift getum við skilgreint mannvirki og flokka.

Báðar smíðarnar eiga margt sameiginlegt og nokkurn mun.

Aðalmunurinn er sá:

Bekkir eru viðmiðunartegundir og mannvirki eru tegundir

Tilvitnun í skjölin:

Gildistegund er gerð sem gildið er afritað þegar það er úthlutað til breytu eða stöðugs eða þegar það er sent í aðgerð.
Öll mannvirki og upptalningar eru tegundir gildi í Swift. Þetta þýðir að öll uppbygging og talningartilfelli sem þú býrð til - og allar tegundir verðmæta sem þeir hafa sem eiginleika - eru alltaf afritaðir þegar þeim er komið fyrir í kóðanum þínum.
Ólíkt gildistegundum, eru viðmiðunartegundir ekki afritaðar þegar þeim er úthlutað til breytu eða stöðugs, eða þegar þeim er komið í aðgerð. Frekar en afrit er tilvísun í sama núverandi dæmi notuð.

Til að sjá hvað þetta þýðir skaltu íhuga eftirfarandi dæmi þar sem við endurnýjum bekkinn Persóna til að gera hann stökkbreytanlegan:

bekkjarpersóna {
  var nafn: String
  var aldur: Int
  var hæð: Tvöfalt
  init (nafn: Strengur, aldur: Int, hæð: tvöfalt) {
    self.name = nafn
    sjálf.age = aldur
    self.height = hæð
  }
}
var a = Persóna (nafn: „Andrea“, aldur: 34, hæð: 1,84)
var b = a
b.age = 35
prenta (a.age) // prenta 35

Ef við skilgreinum Persónu til að vera mannvirki höfum við þetta:

mannvirki manneskju {
  var nafn: String
  var aldur: Int
  var hæð: Tvöfalt
  init (nafn: Strengur, aldur: Int, hæð: tvöfalt) {
    self.name = nafn
    sjálf.age = aldur
    self.height = hæð
  }
}
var a = Persóna (nafn: „Andrea“, aldur: 34, hæð: 1,84)
var b = a
b.age = 35
prenta (a.age) // prenta 34

Það er miklu meira í mannvirkjum en ég hef fjallað um hér.

Hægt er að nota mannvirki til að meðhöndla gögn og gerðir í Swift, sem leiðir til öflugs kóða með færri galla.

Til að fá betri yfirsýn, lestu: Structures and Classes in Swift.

Villa við meðhöndlun

Notkun skilgreiningar frá Swift skjölunum:

Villa við meðhöndlun er ferlið við að bregðast við og batna frá villuaðstæðum í forritinu þínu.

Bæði Dart og Swift nota try / catch sem tækni til að meðhöndla villur, með nokkrum mismun.

Í Dart getur hvaða aðferð sem er kastað undantekningu af hvaða gerð sem er.

bankareikningur bekkjar {
  BankAccount ({this.balance});
  tvöfalt jafnvægi;
  ógilt afturköllun (tvöföld upphæð) {
    ef (upphæð> staða) {
      kasta undantekningu ('Ófullnægjandi fjármagn');
    }
    jafnvægi - = upphæð;
  }
}

Undantekningar er hægt að veiða með reyna / grípa blokk:

var reikningur = BankAccount (staða: 100);
reyndu {
  reikningur.withdraw (50); // allt í lagi
  reikningur. útdráttur (200); // kastar
} veiða (e) {
  prenta (e); // prentar 'Undantekning: Ófullnægjandi sjóðir'
}

Í Swift lýsum við því nákvæmlega yfir hvenær aðferð getur varpað undantekningu. Þetta er gert með kastar leitarorðinu og allar villur verða að vera í samræmi við villuferlið:

enum AccountError: Villa {
  tilfelli ófullnægjandi
}
bankareikningur bekkjar {
  var jafnvægi: tvöfalt
  init (jafnvægi: tvöfalt) {
    self.balance = jafnvægi
  }
  func draga (upphæð: tvöfalt) kastar {
    ef upphæð> staða {
      henda AccountError.insufficientFunds
    }
    jafnvægi - = upphæð
  }
}

Þegar við meðhöndlum villur notum við reynsluborð í do / catch blokk.

var reikningur = bankareikningur (staða: 100)
gera {
  Prófaðu reikninginn. Dragðu (upphæð: 50) // allt í lagi
  prófa reikning. útfæra (upphæð: 200) // kast
} veiða AccountError.insufficientFunds {
  prenta ("Ófullnægjandi sjóðir")
}

Athugaðu hvernig reyna lykilorð er skylt þegar hringt er í aðferðir sem geta hent.

Og villurnar sjálfar eru sterklega slegnar inn, þannig að við getum haft marga aflablokka til að fjalla um öll möguleg tilvik.

reyna, reyna ?, reyna!

Swift býður upp á minna munnlegar leiðir til að takast á við villur.

Við getum notað reynt? án do / catch block. Og þetta mun valda því að horfa framhjá öllum undantekningum:

var reikningur = bankareikningur (staða: 100)
reyna? account.withdraw (upphæð: 50) // ok
reyna? account.withdraw (upphæð: 200) // mistakast hljóðalaust

Eða ef við erum viss um að aðferð henti ekki, getum við notað try !:

var reikningur = bankareikningur (staða: 100)
reyndu! account.withdraw (upphæð: 50) // ok
reyndu! account.withdraw (upphæð: 200) // hrun

Dæmið hér að ofan mun valda því að forritið hrynur. Prófaðu því! er ekki mælt með í framleiðslu kóða og það hentar betur þegar þú skrifar próf.

Á heildina litið er afdráttarlaust eðli meðhöndlunar villna í Swift mjög gagnlegt við API-hönnun, því það gerir það auðvelt að vita hvort aðferð getur eða ekki hent.

Sömuleiðis vekur athygli reynslunnar í aðferðum símtala athygli á kóða sem geta hent og neyðir okkur til að huga að villumálum.

Að þessu leyti líður meðhöndlun villna öruggari og öflugri en í Dart.

Lestu meira:

  • Píla undantekningar
  • Snögg Villa við meðhöndlun

Generics

Vitna í skjótt skjal:

Almennur kóða gerir þér kleift að skrifa sveigjanlegar, endurnýtanlegar aðgerðir og gerðir sem geta unnið með hvaða gerð sem er, með fyrirvara um kröfur sem þú skilgreinir. Þú getur skrifað kóða sem forðast tvíverknað og tjáð ásetning sinn á skýran, ágripslegan hátt.

Generics eru studd af báðum tungumálum.

Eitt algengasta tilfellið fyrir samheitalyf er safn, svo sem fylki, sett og kort.

Og við getum notað þær til að skilgreina okkar eigin gerðir. Hérna er hvernig við myndum skilgreina almenna stafla gerð í Swift:

struct stack  {
  var hlutir = [Element] ()
  mutating func push (_ atriði: Element) {
    items.append (item)
  }
  mutating func pop () -> Element {
    skila hlutum. Fjarlægja síðast ()
  }
}

Á sama hátt, í Dart, myndum við skrifa:

bekkur stafla  {
  var hlutir =  []
  ógilt ýta (frumefni) {
    items.add (atriði)
  }
  tómt popp () -> Element {
    skila hlutum. Fjarlægja síðast ()
  }
}

Rafskautar eru mjög gagnlegar og öflugir í Swift þar sem hægt er að nota þær til að skilgreina tegundartakmarkanir og tilheyrandi gerðir í samskiptareglum.

Ég mæli með að lesa skjölin til að fá frekari upplýsingar:

  • Swift Generics
  • Dart Generics

Aðgangsstýring

Tilvitnun í Swift skjölin:

Aðgangsstýring takmarkar aðgang að hluta kóðans þíns frá kóða í öðrum upprunaskrám og einingum. Þessi aðgerð gerir þér kleift að fela útfærsluupplýsingar kóðans þíns og tilgreina valinn viðmót sem hægt er að nálgast og nota þann kóða.

Swift er með fimm aðgangsstig: opið, opinbert, innra, skjalasniðið og lokað.

Þetta er notað í samhengi við að vinna með einingar og upprunaskrár. Tilvitnun:

Eining er ein eining af dreifingu kóða - ramma eða forrit sem er smíðað og flutt sem ein eining og sem hægt er að flytja inn af annarri einingu með innflutningsorðsorði Swift.

Hægt er að nota opna og almenna aðgangsstigin til að gera kóða aðgengilegan utan eininga.

Hægt er að nota einkaaðgangsstigið og skráa-einkaaðgangsstigið til að gera kóðann ekki aðgengilegan utan skráarinnar sem hann er skilgreindur í.

Dæmi:

almenningsflokkur SomePublicClass {}
innri flokkur SomeInternalClass {}
fileprivate class SomeFilePrivateClass {}
einkatímarit SomePrivateClass {}

Aðgangsstig eru einfaldari í Dart og takmarkast við almenning og einkaaðila. Tilvitnun:

Ólíkt Java, hefur Dart ekki leitarorðin opin, vernd og einkaaðila. Ef auðkenni byrjar með undirstrikun _ er það lokað fyrir bókasafnið.

Dæmi:

bekk Heimasíða nær StatefulWidget {// almenningur
  @ yfirride
  _HomePageState createState () => _HomePageState ();
}
bekk _HomePageState nær ríki  {...} // einkaaðila

Aðgangsstýring var hönnuð með mismunandi markmið fyrir Dart og Swift. Og þar af leiðandi eru aðgangsstigin mjög mismunandi.

Lestu meira:

  • Snögg aðgangsstýring
  • Pílabókasöfn og skyggni

Ósamstilltur forritun: Framtíðir

Ósamstilltur forritun er svæði þar sem Dart skín virkilega.

Einhvers konar ósamstilltur forritun er nauðsynleg þegar verið er að fjalla um notkunartilvik eins og:

  • Að hala niður efni af vefnum
  • Talandi við stuðningsþjónustu
  • Framkvæma aðgerð í langan tíma

Í þessum tilvikum er best að loka ekki á aðalþræðina sem keyrir, sem getur látið forritin okkar frysta.

Tilvitnun í skjöl Dart:

Ósamstilltur aðgerð lætur forritið ljúka annarri vinnu á meðan beðið er eftir að aðgerð ljúki. Dart notar framtíðarhluti (framtíð) til að tákna niðurstöður ósamstilltra aðgerða. Til að vinna með framtíð geturðu notað annaðhvort ósamstillt og beðið eða API fyrir framtíðina.

Sem dæmi, við skulum sjá hvernig við getum notað ósamstilltur forritun til að:

  • sannvotta notanda með netþjóni
  • geymdu aðgangsmerkið til að tryggja geymslu
  • fáðu upplýsingar um notandasniðið

Í Dart er hægt að gera þetta með async / bíða ásamt Futures:

Framundan  getUserProfile (UserCredentials persónuskilríki) ósamstilltur {
  endanleg accessToken = bíða eftir netService.signIn (skilríki);
  bíða öruggurStorage.storeToken (accessToken, forUserCredentials: legitimations);
  aftur bíða netþjónustan.getProfile (accessToken);
}

Í Swift er enginn stuðningur við ósamstillingu / bíða og við getum aðeins náð þessu með lokunum (lokið blokkir):

func getUserProfile (skilríki: UserCredentials, lokið: (_ niðurstaða: UserProfile) -> Ógilt) {
  netService.signIn (skilríki) {accessToken in
    secureStorage.storeToken (accessToken) {
      netService.getProfile (accessToken, lokið: lokið)
    }
  }
}

Þetta leiðir til „dómspíramídans“ vegna hreinsaðra lokakubba. Og meðhöndlun villna verður mjög erfið í þessari atburðarás.

Í Dart er meðhöndlunarvillur í kóðanum hér að ofan einfaldlega gert með því að bæta við reyna / grípa blokk kringum kóðann við getUserProfile aðferðina.

Til viðmiðunar er tillaga um að bæta Swyn í óheillavænleika / bíða í framtíðinni. Þetta er skjalfest í smáatriðum hér:

  • Async / Bíða eftir tillögu fyrir Swift

Þangað til þetta er komið í framkvæmd geta verktaki notað bókasöfn frá þriðja aðila eins og þetta Promises bókasafn frá Google.

Hvað Dart varðar, þá er að finna frábæru skjöl hér:

  • Dart ósamstilltur forritun: framtíð

Ósamstilltur forritun: Straumar

Straumar eru útfærðir sem hluti af Dart kjarnasöfnum en ekki í Swift.

Tilvitnun í skjöl Dart:

Straumur er röð ósamstilltra atburða.

Straumar eru undirstaða viðbragðs forrita, þar sem þeir gegna mikilvægu hlutverki með stjórnun ríkisins.

Til dæmis eru straumar frábært val til að leita að efni, þar sem nýtt sett af niðurstöðum er sent frá sér í hvert skipti sem notandinn uppfærir textann í leitarreitnum.

Straumar eru ekki með í Swift kjarnasöfnum. Bókasöfn þriðja aðila eins og RxSwift bjóða upp á stuðning við læki og margt fleira.

Straumar eru breitt efni sem ekki er fjallað um hér.

Lestu meira: Dart ósamstilltur forritun: Straumar

Minni stjórnun

Dart heldur utan um minni með háþróaðri sorphirðukerfi.

Swift heldur utan um minni með sjálfvirkri tilvísunartalningu (ARC).

Þetta tryggir frábæra frammistöðu vegna þess að minni losnar strax þegar það er ekki notað lengur.

Það breytir þó byrðinni að hluta frá þýðandanum yfir í framkvæmdaraðila.

Í Swift verðum við að hugsa um líftíma og eignarhald á hlutum og nota viðeigandi lykilorð (veikt, sterkt, óeðlilegt) rétt til að forðast að viðhalda hringrás.

Lestu meira: Snögg sjálfvirk tilvísun talning.

Samantekt og framkvæmd

Fyrst af öllu, mikilvægur greinarmunur á réttlátur-í-tíma (JIT) og framundan (AOT) þýðendur:

JIT þýðendur

JIT þýðandi keyrir við framkvæmd forritsins og tekur saman á flugu.

JIT þýðendur eru venjulega notaðir með kraftmiklum tungumálum, þar sem gerðir eru ekki lagaðar fyrirfram. JIT forrit keyra um túlk eða sýndarvél (VM).

AOT þýðendur

AOT þýðandi keyrir við gerð forritsins, áður en tíminn rennur út.

AOT þýðendur eru venjulega notaðir með kyrrstæðum tungumálum, sem þekkja gerðir gagnanna. AOT forrit eru tekin saman í innfæddur vélakóði sem er keyrður beint af vélbúnaðinum þegar kemur að því.

Vitnað í þessa frábæru grein eftir Wm Leler:

Þegar AOT samantekt er unnin meðan á þróun stendur leiðir það ávallt til mun hægari þróunarferla (tíminn á milli þess að breyta í forriti og að geta framkvæmt forritið til að sjá niðurstöðu breytinganna). En AOT samantekt skilar sér í forritum sem geta keyrt meira fyrirsjáanleg og án þess að gera hlé til greiningar og samantektar í keyrslu. AOT saman forrit byrja einnig að keyra hraðar (vegna þess að þau hafa þegar verið tekin saman).
Hins vegar veitir JIT samantekt mun hraðari þróunarferli, en getur valdið hægari eða skíthæll framkvæmd. Sérstaklega hafa JIT þýðendur hægari gangsetningu, því þegar forritið byrjar að keyra verður JIT þýðandinn að gera greiningar og samantekt áður en hægt er að keyra kóðann. Rannsóknir hafa sýnt að margir munu yfirgefa forrit ef það tekur meira en nokkrar sekúndur að hefja keyrslu.

Sem kyrrstætt tungumál er Swift tekið saman fyrirfram.

Hægt er að setja saman pílu bæði AOT og JIT. Þetta veitir umtalsverða kosti þegar það er notað með Flutter. Tilvitnun aftur:

JIT samantekt er notuð við þróun, með því að nota þýðanda sem er sérstaklega hratt. Þegar app er tilbúið til útgáfu þá er það tekið saman AOT. Þar af leiðandi, með hjálp háþróaðra verkfæra og þýðenda, getur Dart skilað því besta frá báðum heimum: ákaflega hröð þróunarferli og fljótur framkvæmd og gangsetningartími. - Wm Leler

Með Dart fáum við besta af báðum heimum.

Swift þjáist af aðal gallanum við AOT samantekt. Það er, samantektartíminn eykst með stærð kóðabasans.

Fyrir meðalstórt forrit (milli 10K og 100K línur) getur það auðveldlega tekið nokkrar mínútur að setja saman app.

Ekki svo með Flutter forritin, þar sem við fáum stöðugt upphleðslu undir sekúndu, óháð stærð codebase.

Aðrir eiginleikar ekki fjallað

Eftirfarandi aðgerðir voru ekki fjallað þar sem þær eru mjög svipaðar í Dart og Swift:

  • Rekstraraðilar (sjá tilvísun fyrir Swift og Dart)
  • Strengir (sjá tilvísun fyrir Swift og Dart)
  • Valfrjáls keðja í Swift (þekktur sem skilyrt aðgangur að meðlimum í Dart).

Samhliða

  • Samhliða forritun er þetta með einangrun í Dart.
  • Swift notar Grand Central Dispatch (GCD) og sendingarröð.

Uppáhalds Swift aðgerðir mínar vantar í Dart

  • Mannvirki
  • Enums með tilheyrandi gerðum
  • Valkostir

Uppáhalds Dart aðgerðir mínar vantar í Swift

  • Just-in-time þýðandi
  • Framtíðir með bið / ósamstilltur (sjá ósamstilltur / bíða tillögu Chris Lattner)
  • Straumar með ávöxtun / ósamstillingu * (RxSwift býður upp á yfirborð strauma fyrir viðbrögð)

Niðurstaða

Bæði Dart og Swift eru frábær tungumál, henta vel til að byggja upp nútíma farsímaforrit og víðar.

Hvorugt tungumálið er yfirburða enda hafa þeir báðir sína einstöku sterku stig.

Þegar ég skoða þróun farsímaforrita og verkfærið fyrir tungumálin tvö finnst mér Dart hafa yfirhöndina. Þetta er vegna JIT þýðandans, sem er grunnurinn að ríkjandi hitaleiðhleðslu í Flutter.

Og heitt endurhleðsla skilar miklum framleiðnihækkun þegar forrit eru smíðuð, því það flýtir fyrir þróunarferlinu úr sekúndum eða mínútum í minna en sekúndu.

Tími verktaki er af skornum skammti en tölvutími.

Svo að fínstilla fyrir tíma verktaki er mjög snjallt.

Aftur á móti finnst mér að Swift sé með mjög sterkt tegundakerfi. Tegundaröryggi er bakað í öllum tungumálareiginleikum og leiðir náttúrulega til öflugra forrita.

Þegar við leggjum til hliðar persónulegar óskir eru forritunarmál bara tæki. Og það er starf okkar sem verktaki að velja heppilegasta tækið fyrir starfið.

Í öllum tilvikum getum við vonað að bæði tungumálin láni bestu hugmyndirnar hvert af öðru þegar þau þróast.

Tilvísanir

Bæði Dart og Swift eru með umfangsmikið lögunarsett og hefur ekki verið fjallað að fullu hér.

Ég undirbjó þessa grein lántökuupplýsingar úr opinberum Swift og Dart skjölum, sem finna má hér:

  • Snögg forritunarmálið
  • A Tour of the Dart Language

Að auki er hluti um JIT og AOT þýðendur mjög innblásinn af þessari frábæru grein Wm Leler:

  • Af hverju flöktur notar pílu

Hef ég misst af einhverju? Láttu mig vita í athugasemdunum.

Sæl kóðun!

UPDATE: My Flutter & Firebase Udemy námskeiðið er nú í boði fyrir snemma aðgang. Notaðu þennan hlekk til að skrá þig (afsláttarkóði innifalinn):

  • Flutter & Firebase: Byggja heill app fyrir iOS & Android

Fyrir fleiri greinar og kennsluefni við vídeó, skoðaðu kóðun með flökt.

Ég er @ biz84 á Twitter. Þú getur líka séð GitHub síðuna mína.