171

Anthony Gray - Swift Espresso

  • Upload
    lele125

  • View
    24

  • Download
    2

Embed Size (px)

DESCRIPTION

Anthony Gray - Swift Espresso

Citation preview

  • Swiftespresso

  • AnthonyGray

    Swiftespresso

    ProgrammazioneperiOSeOSX

    EDITOREULRICOHOEPLIMILANO

  • Titolooriginale:SwiftPocketReferenceProgrammingforiOSandOSX

    Copyright2015AnthonyGray.Allrightsreserved.

    ThistranslationispublishedandsoldbypermissionofOReillyMedia,Inc.,whichownsorcontrolsallrightstopublishandsellthesame.

    Perl'edizioneitaliana

    CopyrightUlricoHoepliEditoreS.p.A.2015

    viaHoepli5,20121Milano(Italy)

    tel.+3902864871fax+39028052886

    [email protected]

    www.hoepli.it

    SeguicisuTwitter:@Hoepli_1870

    Tuttiidirittisonoriservatianormadileggeeanormadelleconvenzioniinternazionali

    ISBNEBOOK978-88-203-6980-4

    Traduzione:FurioPiccinini

    Progettoeditoriale:MaurizioVedovatiServizieditoriali

    ([email protected])

    Copertina:SaraTaglialegne

    Realizzazionedigitale:Promedia,Torino

  • Sommario

    Introduzione

    PrimipassiconSwift

    UnassaggiodiSwift

    Funzionalitdibasedellinguaggio

    Tipi

    Variabiliecostanti

    Tuple

    Operatori

    StringeCharacter

    Array

    Dizionari

    Funzioni

    Closure

    Optional

    Flussodelprogramma

    Classi

    Strutture

    Enumeration

    Controllodiaccesso

    Estensioni

    Verificaecastingdeitipi

    Protocolli

    Gestionedellamemoria

    Generic

    Overloadingdeglioperatori

    Range,intervalliestride

  • Funzioniglobali

    Indiceanalitico

    InformazionisulLibro

  • Introduzione

    Swift un nuovo interessante linguaggio creato daApple, ed stato annunciato per laprimavoltadurantelaAppleWorldwideDevelopersConference(WWDC)nelgiugnodel2014.IllinguaggiohapresovitadaunideadiChrisLattner,direttoredelDeveloperToolsDepartment diApple, e rappresenta il passo successivo nellevoluzione dellecosistemadellosvilupposoftwaredellaziendadellaMela.Swiftportaconsmoltefunzionalitdeilinguaggimoderni,incluselasicurezzadeitipi,igeneric,linferenzadeitipi,leclosure,letuple, la gestione automatica della memoria e il supporto per Unicode (per i valoricarattere e stringa, cos comepergli identificatori).PoteteusareunamisceladiSwift eObjective-C in un singolo progetto e ciascun linguaggio pu chiamare le APIimplementateconlaltro.LasfidaperchiunquevogliaimparareSwift(oanchescriverne)nelfattocheillinguaggioancorainevoluzione.Applehaaffermatochelespecifichedel linguaggionon sonoancora in fase finale e che la sintassi e le funzionalit sarannomodificate. Nonostante le incertezze di un linguaggio in fase di cambiamento, Swiftmostra grandi premesse. Segue direttamente le iniziative riguardanti gli altri principalidevelopertooldellazienda(tuttiguidatidaLattner),inclusiLLVM,Clang,LLDB,ARCeuna serie di estensioni di Objective-C, e appare chiaro che Apple lo considera illinguaggiodelfuturoperlosvilupposoftwaresuiOSeOSX.

    ConvenzioniusateinquestolibroInquestolibrovengonousateleseguenticonvenzionitipografiche:

    Corsivo

    Indicanuovitermini,URL,indirizziemail,nomidifileedestensioni.Monospaziato

    usatoperilistatidiunprogramma,oltrecheallinternodeiparagraficomeriferimentoaelementi di un programma, come variabili o nomi di funzioni, database, tipi di dati,variabilidambiente,dichiarazionieparolechiave.Monospaziatograssetto

    Mostracomandioaltrotestochedevonoesseredigitaticonprecisionedallutente.Monospaziatocorsivo

    Mostra il testo che deve essere sostituito con i valori forniti dallutente o con quellideterminatidalcontesto.

    NOTA

  • Questoelementoindicaunanotagenerica.

    UsodegliesempidicodiceQuesto libro stato scritto e pubblicato per aiutarvi a completare il vostro lavoro. Ingenere,seneltestoincontrateunesempiodicodice,poteteusarlonelvostroprogrammaenelladocumentazione.Nonnecessariochecicontattiateperottenereilpermessoalluso,ameno che non stiate riproducendo una porzione significativa di codice. Per esempio,scrivereunprogrammacheusadiversepartidicodicetrattedaquestolibrononrichiedealcun permesso. Vendere o distribuire un CD-ROM di esempi tratti dai libri Hoeplirichiede invece tale permesso. Rispondere a una domanda citando questo libro eriportandolesempiodicodicenonrichiedealcunpermesso.Incorporareunasignificativaquantit di codice di questo libro nella documentazione di un vostro prodotto richiedeinvecetalepermesso.

    Apprezziamo le citazioni, che, tuttavia, non sono richieste. Una citazione normalmenteincludeiltitolo,lautore,leditoreeilcodiceISBN.Peresempio:SwiftPocketReferencediAnthonyGray(Hoepli).Copyright2015AnthonyGray,978-88-203-6702-2.

    Sepensatechelusochefatedegliesempidicodicericadaaldifuoridegliusiconsentitiodaipermessispecificatiinprecedenza,[email protected].

    ComecontattarciPoteteinviarecommentiedomanderiguardantiquestolibrodirettamentealleditore:

    HoepliS.p.A.

    ViaU.Hoepli,5

    20121Milano

    Per commentare o porgere domande tecniche su questo libro, inviate una email [email protected].

    RiconoscimentiVoglio ringraziare Paris Buttfield-Addison per avermi spinto (ripetutamente) a scriverequesto libro.Luie lasuapartner, JonManning,sonoaffettidaottimismosenza limitiesembranoprendereunnocomeunasfidaanzichunasconfitta.

    RingrazioancheRachelRoumeliotiselealtrepersoneveramentespecialiinOReilly,peraver creduto in me e per avermi guidato lungo i vari passi del progetto, fino al suocompletamento.

    Unringraziamentovaancheailettoridelleprimebozze,chesisonoadoperatiperfornirefeedback e suggerimenti permigliorare il lavoro, cosa per la quale sono estremamentegratoatuttiloro.

  • NotesullautoreAnthonyGray(potetechiamarloTony)haunalungastoriacomeprofessionistanelsettoreeducational,nelqualehafornitoilpropriosupportotecnicoanumerosistaffaccademiciedi ricerca, oltre che a molti studenti particolarmente brillanti. Adora insegnare, inparticolar modo nei settori dei sistemi operativi, computer grafica e animazioni conOpenGL e, in tempi recenti, dello sviluppo mobile per iOS. Nel tempo libero scrivesoftwareperpassioneepotetetrovarealcunideisuoilavorialsitosquidman.net.Ingransegreto rimpiange i giorni in cui si poteva programmare in assembler per il 6502 eoccasionalmentescrivedegliemulatori,cosdapoterlofareancora.

  • PrimipassiconSwift

    Per programmare con il linguaggio Swift dovete usare Xcode 6.1 o le sue successiveversioni(disponibilegratuitamentesulMacAppStore),chepuessereeseguitoinOSX10.9(Mavericks)oOSX10.10(Yosemite).PotresteancheconsiderarediregistrarvicomeAppledeveloper(esistonoprogrammigratuitieapagamento),cosdaottenerelaccessoauna grande quantit di documentazione e altre risorse per sviluppatori al sitohttps://developer.apple.com.Poteteusare laversionediSwift integrata inXcode6.1percompilareiprogrammichefunzionerannosuOSX10.9eOSX10.10,oltrechesuiOS7eiOS8.

    Dopo aver scaricato e installato Xcode 6.1, eseguitelo e consentitegli di installare inumerosistrumenticorrelati.Quandolinstallazionesarcompletata,avretediversimodiperiniziareconSwift:

    Fate clic su File NewProject per creare un nuovo progettoXcode.Vieneapertoilprojectwizard,chevioffrelasceltatralusodiSwiftodiObjective-Ccomelinguaggioperilprogetto.

    FateclicsuFile NewPlaygroundpercreareunnuovodocumentoplayground.I playground sono ambienti dinamici a singola finestra, nei quali potetesperimentare le funzionalit del linguaggio Swift e osservare istantaneamente irisultatimentredigitateilcodice.

    CreateunoscriptSwiftedeseguitelodarigadicomandonelterminaleOSX.

    UsateloSwiftRead-Evaluate-Print-Loop(REPL)nelterminaleOSX.

    DiamounosguardopiapprofonditoaREPL,alloscriptingSwifteaiplayground.

    Almomento in cui scriviamo, alcune funzionalit di Swift e diXcode 6.1 sono ancorainstabili.probabilechepossiateincorrereinalcuneinstabilitdeiplaygroundSwift,coscomenellefunzionidiautocompletamentoedevidenziazionedellasintassidiXcode.Neiplayground, il risultato di unespressione potrebbe non essere sempre visualizzato nellabarradei risultati,mapotrebbecomparire inunarigaprecedente.AvoltepotrestedoverchiudereeriavviareXcodeperfarlotornarepienamenteoperativo.

    IlREPLSwiftIlREPLSwiftforniscelaccessoaSwifttramiterigadicomandoesicomportacomeuninterprete. Potete dichiarare variabili e costanti, definire funzioni, valutare espressioni eusare lamaggiorpartedelle funzionalitdel linguaggio:verrannocompilateedeseguiteimmediatamente.

  • InstallazionimultiplediXcodeSe disponete di pi di uninstallazione di Xcode sul vostro computer, dovrete usare ilcomandoxcode-select per selezionare lambienteXcode6 comedirectory di sviluppoattiva.Tramiteilterminale,digitateilseguentecomando:sudoxcode-select-s/Applications/Xcode.app

    Quandorichiesto,digitatelousernameelapassworddiamministratore.SeaveteinstallatoXcodeinunaposizionediversaoseneavetecambiatoilnome,sostituiteilpercorsonelcomandoconlaposizioneeilnomedellareleasecheaveteinstallato.

    AvviareilREPLPeravviareilREPL,inmododapotertestarelefunzionalitdellinguaggioSwift,usateilseguentecomando:xcrunswift

    SenonavetemaiusatoprimaXcode,potrestericevereunarichiestadiautenticazionedaparte di un processo chiamato Developer Tools Access (vedere la Figura 1), che vichiederusernameepassword.Perpoterproseguire,dovretedigitareivostriusernameepassworddiamministratore.Inseguitopotrestevedereilseguentemessaggiodierrore(suOSX10.9):error:failedtolaunchREPLprocess:processexitedwithstatus-1(lostconnection)

    Aquestopunto,digitatenuovamenteilcomandoxcrunswift.StavoltailREPLdovrebbeavviarsinormalmente.

    AllavviodelREPLvedreteilseguenteoutput:

    WelcometoSwift!Type:helpforassistance.1>

    Figura1LafinestradelprocessoDeveloperToolsAccess.

    OrasieteprontiaprovareilvostrocodiceSwift.Sperimentatelafunzioneprintln:1>println(Hello,World)

    Hello,World

    2>

  • IlREPLrappresentaunottimometodopertestarelefunzionalitdiSwiftesperimentarelefunzionalitdellinguaggio.

    SwiftcomelinguaggiodiscriptingPoteteusareSwiftcome linguaggiodi scripting,propriocomePerl,PythonoRuby.PerusareSwift in questomodo, assicuratevi che la prima riga dello script contenga il pathdellinterprete Swift. Se volete provare Swift in questamodalit, digitate il codice chesegueinunfileditestochiamatohello.swift:#!/usr/bin/swift

    println(Hello,World)

    In seguito, assicuratevi che lo script sia contrassegnato come eseguibile mediante ilcomandochmod:chmodu+xhello.swift

    Oraeseguiteloscriptcomesegue:./hello.swift

    Swiftcompilerilvostroprogrammae,senonsonopresentierroridisintassi,loeseguir.

    IplaygrounddiSwiftPeresplorareSwiftinunplayground,dallabarradeimenudiXcode,fateclicsuFileNewPlaygroundosullopzioneGetstartedwithaplaygroundnellafinestraWelcometoXcode.

    Vi viene chiesto di specificare un nome per il playground (che diventa il nome deldocumentosalvato)eunapiattaforma(iOSoOSX),comemostratoinFigura2.

    Figura2CreazionediunplaygroundinSwift.

    Dopoaverdigitatoilnomedelplaygroundeselezionatolapiattaforma,fateclicsuNext.Vi verr chiesto di selezionare una posizione in cui salvare il file. Dopo il salvataggiovedretelafinestrainizialedelplayground,mostratanellaFigura3.

  • Figura3Lafinestrainizialedelplayground.

    IltemplatedelplaygroundimportailframeworkCocoaoUIKit,asecondadicosaaveteselezionatocomepiattaformadelplayground(OSXo iOS).QuestosignificachepotetesperimentarenonsololefunzionalitdibasedellinguaggioSwift,maanchemoltedellefunzionifornitedalframework,comeperesempioildisegnodivieweimmagini,eanchelimplementazionedelleanimazionidibase.

    Ilplaygroundmostraancheunarigadicodice:varstr=Hello,playground

    A destra di questo codice situato il valore Hello, playground.Questo dimostra unadellefunzionipiutilidelplayground:ilrisultatodiqualunqueespressionevienemostratoafiancodellastessa,nellabarralateraledeirisultati.

    Sottoiltestoesistentedigitatequantosegue:forvari=0;i

  • Figura4AccessoaQuickLookeallaTimelinedallabarralateraledeirisultati.

    La Timeline pu mostrarvi come i valori siano cambiati nel tempo, oltre a mostrareloutputdellaconsole(peresempioiltestoinoutputdellafunzioneprintln).

    Poteteancheaprire laTimelineandandoallabarradeimenudiXcodeefacendoclicsuView AssistantEditor ShowAssistantEditor,oppurepoteteusarelascorciatoiadatastieraComando-Opzione-Invio.

    NOTAPer uneccellente introduzione ai playground, guardate laregistrazione della sessione 408 (Swift Playgrounds), tratta dallaWorldwide Developers Conference del 2014(https://developer.apple.com/videos/wwdc/2014/).

  • UnassaggiodiSwift

    Entriamo nei dettagli. Quello che segue un semplice programma scritto in Swift.Analizzateloconattenzione,percogliereilsensodialcunefunzionalitdellinguaggio.

    Laprimacosacheilprogrammafa,quelladidefinireunacoppiadiarray:unochiamatouserselaltroages,perlagestionedegliutenti.Questiultimiservonoarappresentareuninputgrezzodidatinonassociati,chedevonoessereunitie,quindi,usaticomebaseperunreport://alcunidatigrezzidaprocessare

    varusers=[xavier,ryan,brenda,james,sarah]varages=[32,28,24,41,19]

    LasezioneseguentedelcodicerappresentaunacoppiadiestensionideltipoString.SwiftoffreilsupportointegratoperlestringheUnicode,mahaancheunflessibilemeccanismodi estensione, mediante il quale potete aggiungere nuove funzionalit al linguaggio ancheperitipiintegrati.LanostraestensioneaggiungeduenuovefunzionialtipoString,chepossonoaccettareuna stringa e restituirneunacopia conundeterminatonumerodispaziinizialiofinali,finoalraggiungimentodiunagrandezzaspecificata:

    //aggiuntadiestensionialtipoStringextensionString{

    funcleadingSpaces(width:Int)->String{

    vars=\(self)foriincountElements(s)..String{

    vars=\(self)foriincountElements(s)..

  • }}

    Ora dichiariamo il dizionario merged. Si tratta di un array associativo di coppiechiave/valore, chememorizzano nome ed et di ciascun utente.Dichiariamo anche unavariabile,totalAge,persommaretuttiivaloridellet,cosdapotercalcolareinseguitoletmediadituttigliutenti://undizionarioperarchiviarelinputunificatovarmerged=[String:Int]()vartotalAge=0.0;

    Unavoltadefinitoildizionario,iteriamoneiduearraydiinput,unificandolineldizionariomerged.Questultimousailnomedellutentecomechiaveeletcomevalore://unionediduearrayinundizionario

    forvari=0;ilocoDetail

    {

    //faiqualcosaerestituisciunval.ditipolocoDetail

    }

    Linferenzadeitipifunzionaancheconglialias,pertantoin

  • varanEngine=getNextLoco()

    lavariabileanEnginesaranchessaditipolocoDetail.

    LetuplecometipirestituitiLetuplerappresentanounmetodopraticoperrestituirepidiunvaloredaunafunzioneodaunachiamataaunmetodo.

    Pensate a una funzione che, a ogni chiamata successiva, restituisca la riga seguente ditesto da un file. In un dato momento verr raggiunta la fine del file, cosa che vacomunicataalchiamante.Lostatoend-of-filedevessererestituitoinmodoseparatodallarigaditesto,cosacherisultaperfettaperunatupla:funcreadLine()->(Bool,String)

    {

    }

    Lafunzionepotrebbeancheattribuiredeinomiaiparametridellatupla,comemostratodiseguito:funcreadLine()->(eof:Bool,readLine:String)

    {

    }

    Luso delle tuple in questomodo produce unespressione pi naturale ed evita tecnichemenolimpidepertestaresesiastataraggiuntalaend-of-file.

  • Operatori

    Glioperatorisonosimbolicherappresentanoalcuneoperazionidaeseguiresuvalori (disolitoespressicomecostanti,variabilioespressioni).Esempidioperatorinotiincludonoilsegno pi (+), che normalmente rappresenta laddizione (o, nel caso delle stringhe, ilconcatenamento),eilsegnomeno(-),cherappresentalasottrazione.

    Gli operatori sono spesso caratterizzati comeunari (che operano su un singolo valore),binari(cheoperanosuduevalori),oternari(cheoperanosutrevalori).

    IllinguaggioSwiftsupportaloverloadingdeglioperatori,pertantoimportantericordareche leffettiva operazione eseguita da un operatore sar determinata dal tipo di dato alquale viene applicato. Le descrizioni che seguono si riferiscono al comportamentopredefinito(vedereancheOverloadingdeglioperatoriapag.165).

    ConversionedeltipononimplicitaPrima di considerare gli specifici operatori supportati da Swift, dovete sapere che illinguaggiononesegueunaconversione implicitadel tipo.Questosignificache ilcodicecheseguenonverrcompilato,perchglioperatorifeisonodi tipodiverso(unounDouble,laltrounInt):vari=2

    varf=45.0

    letresult=(f/i)//errore

    AdifferenzadeilinguaggibasatisulLinguaggioC,Swiftnoneseguiralcunaconversioneimplicitadeltiponelleespressionidovreteconvertireesplicitamenteglioperatorialtipodesiderato.Peritipinumerici,questosignificagestireiltipocomeunafunzioneeisuoioperandicomeilrelativoargomento:letresult=(f/Double(i))

    importante notare anche che le regole sullinferenza del tipo di Swift gestiranno unacostante floating-point comeDouble, ameno che la variabile non sia stata inizializzatacome Float. Nellesempio precedente, f oggetto di inferenza e viene trattato comeDouble,noncomeFloat,pertantoideveessereforzato(casting)inDouble.

    OperatoriaritmeticiGlioperatoriaritmeticibinaristandardinSwiftsonoimedesimideglialtrilinguaggi:

    +

  • Addizione (o concatenamento di stringhe, se entrambi gli operandisonostringhe).- Sottrazione.* Moltiplicazione./ Divisione.

    NOTAAdifferenzadi altri linguaggi,Swift non consente di eseguire unoverflowoununderflowusandoquestioperatori.Setalioverflowounderflow dovessero verificarsi, il programma terminerebbe (o ilproblemaverrebbe segnalatoprimadel tempodal compilatore, sepossibile). Per ulteriori informazioni su questo argomento,consultatelasezioneOperatoridioverflowpiavantinellibro.

    ++ Preopost-incremento. Preopost-decremento.

    ComeperilC,questiultimidueoperatoriunariincrementerannoodecrementerannounavariabiledi tipoInt,FloatoDouble, e restituirannoancheunvalore.Quando liusatecomeprefisso(loperatorecompareasinistradelloperando),restituirannoilnuovovalore(incrementato). Quando li usate come suffisso (loperatore compare a destradelloperando),restituirannoilvaloreoriginale(primadellincrementoedecremento).

    OperatoribitwiseGli operatori che seguono vengono usati con i tipi di dati integer e consentono lamanipolazionealivellodibit:

    ~(~A)BitwiseNOT;invertetuttiibitinunnumero.&(A&B)

    BitwiseANDdiAeB.|(A|B)

    BitwiseORdiAeB(AB)

    BitwiseXORdiAeB.

  • Bitwiseleft-shiftdiAperunnumeroBdibit.>>(A>>B)

    Bitwiseright-shiftdiAperunnumeroBdibit.

    Quando loperando a sinistra di tipo unsigned, gli operatori left-shift e right-shifteseguirannounospostamentopervaloridizero.

    Quando loperando a sinistra ha un tipo specificato, gli operatori left-shift e right-shiftpreserveranno sempre il segno dei bit. Loperatore left-shift esegue sempre unospostamentoinnuovivaloriinbitdizero,mentreloperatoreright-shiftloesegueinnuovibitconlostessovaloredelbitdiorigine.

    OperatoridiassegnazioneOltre alloperatore di assegnazione tradizionale (=), tutti gli altri qui descritti sonooperatori di assegnazione composti (per esempio, combinano unaltra operazione, comeladdizioneolasottrazione,allassegnazione):

    = Assegnazione.+= Aggiungeeassegna(a+=nlequivalentedia=a+n).-= Sottraeeassegna(a-=nlequivalentedia=a-n).*= Moltiplicaeassegna(a*=nlequivalentedia=a*n)./= Divideeassegna(a/=nlequivalentedia=a/n).%= Restoeassegna(a%=nlequivalentedia=a%n).>n).&= BitwiseANDeassegna(a&=nlequivalentedia=a&n).|= BitwiseOReassegna(a|=nlequivalentedia=a|n).= BitwiseXOReassegna(a=nlequivalentedia=an).

    NOTA

  • AdifferenzadeilinguaggibasatisulLinguaggioC,glioperatoridiassegnazionenonrestituisconoalcunvalore.Questofattoprevieneun potenziale grave errore, che si verifica qualora digitiateaccidentalmenteunoperatore=inunadichiarazioneif,quandoinrealtvolevateusare==,cosachegeneraunaassegnazioneanzichunacondizioneditest.

    OperatoridiconfrontoGli operatori di confronto restituiscono un valore Booleano che rappresenta se ilconfrontoveroofalso.Luguaglianzaindicaseglioperandiasinistraeadestrahannolostessovalore.Lidentitindicaseglioperatorifannoriferimentoallostessooggetto:==(A==B)

    Testaluguaglianza(stessivalori).!=(A!=B)

    Testaladisuguaglianza.===(A===B)

    Testalidentit(stessioggetti).!==(A!==B)

    Testalanonidentit.=B)

    Testmaggiorediougualea.~=(A~=B)

    Corrispondenzadipattern.

    OperatorilogiciInSwift,ivalorinon-Booleani(comeInt)nonpossonoesserefacilmenteforzatiinvaloriBooleani.QuestioperatoripossonoessereusatisolosuvaloriBool:

    !(!A)

    LogicalNOT;restituisceloppostologicodelloperando.

  • &&(A&&B)

    LogicalAND;restituiscetrueseentrambiglioperatorisonotrue.||(A||B)

    LogicalOR;restituiscetrueseunodeglioperatoritrue.

    OperatoridioverflowGlioperatoridioverflowaccettanosolooperandiditipoenoncausanoalcunerroresesiverificaunoverflowaritmetico:

    &+ Sommaoverflow.&- Sottrazioneoverflow.&* Moltiplicazioneoverflow.&/ Divisioneoverflow(ladivisioneper0restituisce0).&% Restooverflow(ladivisioneper0restituisce0).

    Operatoriperilcastingdeltipois

    Verifica se unistanza di uno specifico tipo di sottoclasse o se unistanza conformeaunprotocollo.as

    Esegueildowncastforzatodellareferencediunistanzaaunospecificotipodisottoclasse,olareferencediunistanzaaunospecificotipodiprotocollo.Seildowncastfalliscesiverificherunerrorediruntime.as?

    Esegueildowncastfacoltativodellareferencediunistanzaaunospecificotipodi sottoclasse, o la reference di unistanza a uno specifico tipo di protocollo.Restituisceunvaloreopzionaleseilnildeldowncastfallisce.

    Consultate anche le sezioni Verifica e casting dei tipi a pagina 135 e Protocolli apagina141.

    OperatoridirangeLoperatore di range chiuso (xy) rappresenta tutti i valori integer che partono da x eterminanoay.xdeveessereminoreougualeay.Questooperatorepuessereusatoinun

  • loop,comenelcodicechesegue:foriin15

    {

    //prenderinsequenzaivalorida1a5

    }

    Loperatoredirangesemi-aperto(x..

  • 4*5+3

    Comeconvenzione,attribuiamoalloperatoredimoltiplicazioneunlivellodiprioritpialtorispettoaquellodiaddizione,pertantolespressionevienevalutatacome23enon32.

    Swift classifica gli operatori integrati come appartenenti a uno tra undici gruppi e usalivellinumericidiprecedenzaperstabilirelordinedivalutazione.Glioperatoridilivellopialtovengonoeseguitiprimadiquelliconlivellobasso.

    Inoltre, quando due operatori con il medesimo livello di precedenza vengono valutati,Swift usa dei valori predefiniti diassociativit per stabilire quale valutare per primo. Ivaloridiassociativitsonodichiaraticomenone,lefteright:

    Unvaloreleftsignificachelapartesinistradellasotto-espressioneverrvalutataperprima.

    Unvalorerightsignificachelapartedestradellasotto-espressioneverrvalutataperprima.

    Unvalorenone significacheglioperatoriconquesto livellodiprecedenzanonpossonoessereadiacentilunoallaltro.

    LaTabella5mostraivaloridiprecedenzaeassociativitperglioperatoriintegrati.

    Tabella5Valoridiprecedenzaeassociativitperglioperatoriintegrati.

    Precedenza Associativit Operatori160 None 150 Left *,/,%,&*,&/,&%,&140 Left +,-,&+,&-,|,135 None ..

  • Sialoperatorediaddizione(+)siaquellodisottrazioneoverflow(&-)hannounlivellodiprecedenza di 150,ma hanno unassociativit di tipo left, il che significa che la sotto-espressioneasinistraverrvalutataperprima,facendoschelespressionesiainterpretatacomesegue:(4+3)&-88

  • StringeCharacter

    Una String (stringa) una collezione ordinata di Characters (caratteri). Il tipoCharacter conforme allo standard Unicode, pertanto anche il tipo String sarpienamentecompatibileconUnicode.

    Levariabilistringaecaratterevuotevengonodichiaratecomesegue:varastring:String

    varachar:Character

    Oppurepossonoessereinizializzateusandounvaloreletterale:varastring:String=Hello

    varachar:Character=A

    Come i valori String, anche quelli Character sono racchiusi tra virgolette (Swift nonconsente di racchiudere i caratteri tra singoli apici, cosa che potrebbe confondere iprogrammatoriinC).

    Poich Swift supporta linferenza dei tipi, non necessario includere la parola chiaveStringquandosiassegnaunvalore,quindipotetescriverelesempioprecedenteinquestomodo:varastring=Hello

    varachar:Character=A

    PoteteconcatenareitipiStringusandoloperatore+percreareunnuovooggettoString:letnewString=Hello+Bill

    OppurepotetecollegareunoggettoStringaunaltrooggettodellostessotipo(String)usandoloperatore+=:varwelcome=Hello

    welcome+=there

    Lestringhesonoun tipodivaloreevengonocopiatequandosonoassegnateopassateauna funzione o a un metodo (a differenza di NSStrings, della quale viene passata lareference).

    ProprietdellestringhePoteteusareleseguentifunzionalitperverificarelalunghezzadiunastringaeottenerevistealternativedellastessaindiversiformatidicarattere:someString.isEmpty

  • Booleano;trueselastringanoncontienecaratteri.countElements(someString)

    Restituisce il numerodi caratteri in una stringa.Dato che le stringhe inSwiftsono compatibili con Unicode, il numero dei caratteri potrebbe non avere lastessalunghezzadellastringainbyte.someString.utf8

    UnavistadellastringainformatoUTF-8(ditipoString.UTF8View),periteraresuicaratteridellastringainformatoa8-bit.someString.utf16

    Una vista della stringa in formato UTF-16 (di tipo String.UTF16View), periteraresuicaratteridellastringainformatoa16-bit.someString.unicodeScalars

    UnavistadellastringainformatoUnicodeScalar(ditipoUnicodeScalarView),periteraresuicaratteridellastringainformatoUnicodeScalar.

    ConfrontotrastringhePotete confrontare stringhe e sotto-stringhe usando i seguenti operatori e metodi diconfronto:

    == Restituiscetrueseduestringhecontengonolastessasequenzadicaratteri.!= < Restituiscetrueseduestringhecontengonounasequenzadiversadicaratteri.<

    Restituiscetrue se la stringaa sinistradelloperatorehaprecedenzadiordinealfabeticorispettoaquellaadestradelloperatore.= Restituisce true se la stringa a sinistra delloperatore non ha precedenza diordinealfabeticoougualeaquellaadestradelloperatore.

    someString.hasPrefix(prefixString)

    Restituisce true se la sequenza di caratteri in prefixString corrispondealliniziodisomeString.

    someString.hasSuffix(suffixString)

  • Restituisce true se la sequenza di caratteri in suffixString corrisponde allafinedisomeString.

    CaratteridiescapenellestringhePer poter usare alcuni caratteri speciali nelle stringhe, dovete usare una sequenza dibackslashcomeformadiescape:

    \0 CarattereNull.\\ Backslash.\t Tab.\n Linefeed.\r Carriagereturn.\ Doppievirgolette.\ Singoloapice.\u{n} ScalareUnicodearbitrario;nvada1a8cifreesadecimali.

    InterpolazionedellestringheUsando una sequenza di escape, possibile valutare delle espressioni e sostituire ilrisultatoinunastringa:\(expr)

    Peresempio:letcostOfMeal=56.52

    letadvice=Considertippingaround\(costOfMeal*0.20)

    Linterpolazionedellestringhenonlimitataaisolivalorinumerici:leta=Hi

    letb=there

    letc=\(a)\(b)//coraHithere

  • Array

    Unarrayunacollezionedielementidellostessotipo,chesitrattidiunosemplice(comeInt,Double,oString)opicomplesso (comeunaclasseostruttura).Poteteaccedereagli elementi in un array in base alla posizione nella collezione, usando una sintassispecifica.Questoesempioassegnailsestoelementodellarrayallacostantev(perchglielementidellarraypartonodallo0):letv=vertex[5]

    Il tipo di un array viene specificato formalmente come Array, sebbene spessovenga usata la versione equivalente e abbreviata [Type]. Per questo, quando vedete iltermine[String],poteteconcluderechesitrattadiunarrayditipoString.

    Potetedichiararegliarrayinmodosimileacomefateperlevariabilielecostanti.Createdegliarrayvuotinelmodoseguente:vararrayName=[Type]()

    vardaysPerWeek=[String]()

    Potetedichiararegliarrayconunospecificonumerodielementipreinizializzati:varvertex=[Double](count:3,repeatedValue:0.0)

    Oppurepoteteinizializzarliusandounarrayletterale:varlocos:[String]=[PuffingBilly,Thomas]

    letdaysPerMonth:[Int]=

    [31,28,31,30,31,30,31,31,30,31,31,31]

    letprimes=[1,3,5,7,11]

    Potete anche usare loperatore + per creare un array che combini array esistenti dellostessotipo,comemostratodiseguito:letvowels=[A,E,I,O,U]

    letconsonants=[B,C,D,F,G,H,J,]

    varallLetters=vowels+consonants

    EccoaltrecaratteristicheaggiuntivedegliarrayinSwift:

    Gliarraydichiaratiusandovarsonomutabili,mentrequellicreaticonlet sonoimmutabili.

    Un tipodi arraynon richiededi essere specificato, seviene inizializzatodaunarrayletterale,perchiltipopuesseredeterminatograzieallinferenza.

    Tuttigli inserimenti inunarraydevonoesseredelmedesimo tipo (adifferenza

  • della classe NSArray di Objective-C, che pu memorizzare una collezione dioggettiarbitrari).

    Gliarraysonountipodivaloreevengonocopiatiquandosonoassegnatiopassatia una funzione o metodo (a differenza di NSArray, che viene passato tramiteriferimento).

    AccedereaglielementidiunarrayPotete accedere agli elementi di un array usando una sintassi simile a quella delLinguaggioC.Ricordatecheilprimoelementodiunarrayhaindiceparia0:letdays=daysPerMonth[5]

    possibileaccedereancheaunsotto-setdielementiinununicavoltausandounrange.Questaoperazionerestituisceunnuovoarray:letnewArray=oldArray[57]

    Se tentate di accedere a un elemento oltre la fine dellarray, si verificher un errore diruntime.arrayName.first

    Restituisceilprimoelementodellarray.arrayName.last

    Restituiscelultimoelementodellarray.

    ProprietdellarrayPeresaminareleproprietdiunarray,usateleseguentifunzionalit:arrayName.capacity

    Integer: il numero di elementi che larray pu memorizzare senza che vengaricollocatoinmemoria.arrayName.count

    Integer:ilnumerodielementinellarray.arrayName.isEmpty

    Boolean:true,selarraynonpossiedeelementi.

    ModificareunarraymutabilePotetemodificaregliarraymutabilineiseguentimodi:arrayName.append(value)

    Aggiungeunnuovoelementoallafinedellarray.arrayName+=array

  • Aggiunge(copia)unarrayallafinediunaltro.arrayName[n]=value

    Memorizzaunvalorenellelementon,sostituendoilvaloreesistente.Secercatediscrivereoltrelafinedellarray,siverificherunerrorediruntime.Peraumentarelarray(peresempio,peraggiungerepiinserimenti),usateilmetodoappend.arrayName[range]=array

    Sostituisceun rangedi elementi conun arraydello stesso tipo. I rangevengonospecificati come [startend]. Tutti gli elementi da [start] a [end] verrannorimossi e sostituiti con copie degli elementi nellarray. La dimensione del rangenon deve essere la stessa dellarray che lo sostituisce; larray si espander orimpicciolirpercontenerelasostituzione.arrayName.insert(value,atIndex:n)

    Inserisceunnuovovaloredavantiallelementon.arrayName.removeAll(keepCapacity:Bool)

    Rimuovetuttiglielementidallarray.LargomentokeepCapacityfacoltativoehail valore predefinito false. Se impostato a true, la capacit dellarray rimarrinalterata.arrayName.removeAtIndex(n)

    Rimuove(erestituisce)lelementondellarray.arrayName.removeLast()

    Rimuove(erestituisce)lultimoelementodellarray.arrayName.reserveCapacity(n)

    Siassicurachelarrayabbiaunacapacitsufficientepermemorizzarenelementisenzaunulterioreriposizionamento,ricorrendovisenecessario.arrayName.sort

    Ordinaglielementidellarray.Vieneusatoconunaclosureperdefinirecomedueelementi devono essere ordinati in relazione luno allaltro (per esempio,names.sort{$0

  • Ilcodicetraparentesigraffevieneeseguitoperciascunelementonellarray.

    Perciascunaesecuzione,itemassumeilvaloredellelementosuccessivo,apartiredalprimo.

    item unaconstante sebbene il suovalore cambi aogni iterazione,nonpuesseremodificatonelloop.

    Per usare sia la posizione sia il valore degli elementi dellarray, usate la funzioneenumerate,comemostratoquisotto:for(index,item)inenumerate(arrayName)

    {

    }

    La funzione enumerate() restituisce una tupla contenente gli integer dellindice e delvaloreperciascunelementodellarray.

    AlgoritmidegliarrayLamaggiorpartedeglialgoritmichepoteteapplicareagliarrayusaleclosure.Sitrattadifunzionianonimecheeseguonodelleoperazionisuunoodueelementidellarray(comeuna trasformazione o un confronto). Consultate la sezione Closure a pagina 61 perulterioriinformazioni.

    Gliesempicheseguonofannousodiquestoarraydistringhe:varnames=[John,Zoe,Laura,albert,Allen]

    arrayName.filter()

    Restituisce un nuovo array che contiene solo gli elementi che corrispondono adalcune condizioni, che sonodefinite usandouna closure.Questo esempio filtra inomipilunghidiquattrocaratteri:names.filter{countElements($0)>4}

    //restituisce[Laura,albert,Allen]

    arrayName.map()

    Restituisce un nuovo array in cui ciascun elemento stato trasformato da unafunzionemapping,chedefinitausandounaclosure.Questoesempio restituisceunarray incuiperogni stringadellarraydioriginechenon iniziaconunaAmaiuscolavieneaggiuntounasterisco(*)comeprefisso:names.filter{$0.hasPrefix(A)?$0:*+$0}//restituisce:

    //[*John,*Zoe,*Laura,*albert,Allen]

    arrayName.reduce()

    Restituisce un singolo valore (del tipo memorizzato nellarray), derivato

  • dallapplicazionericorsivadiunfiltrodiriduzione(definitousandounaclosure),aciascun elemento dellarray e dalloutput del ciclo precedente. Questo esempioverifica il ciclo in base a una stringa vuota ($0) e concatena ciascun elementodellarray($1)alloutputdelcicloprecedente($0):names.reduce(){$0+$1}

    //restituisceJohnZoeLauraalbertAllen

    arrayName.reverse()

    Restituisce un nuovo array che contiene gli elementi di arrayName in ordineinverso,comemostratoquidiseguito:names.reverse()

    //restituisce[Allen,albert,Laura,Zoe,John]

    arrayName.sorted()

    Restituisce un nuovo array che contiene gli elementi diarrayName in un ordinespecifico.Perdefinirecomedueelementivenganoordinatilunorispettoallaltro,vieneusataunaclosure.Peresempio:names.sorted{$0

  • Dizionari

    Propriocomegliarray,idizionarimemorizzanounacollezionedivalori.Ma,mentreglielementidellarrayvengonoreferenziati tramiteposizione,quellideldizionariovengonoreferenziatitramitechiaviunivoche.

    Il tipo di un dizionario viene specificato formalmente come Dictionary,sebbeneesistaanchelaformaabbreviata[KeyType:ValueType].Perquestomotivo,sevedeteiltermine[String:Int],potetedesumerechesitrattidiundizionarioilcuitipodichiaveStringeilcuitipodivaloreInt.

    Idizionarivengonodichiaratiinmodosimileavariabiliecostanti.Potetecrearedizionarivuotinelmodoseguente:vardictionaryName=[Type:Type]()

    varcpus=[String:String]()

    Oppure potete inizializzarli al momento della dichiarazione, usando un dizionarioletterale,comedimostratoquisotto:varcpus:[String:String]=

    [BBCModelB:6502,Lisa:68000,TRS-80:Z80]

    Il tipodellachiaveedelvalorepuessereoggettodi inferenza,quandoquestielementivengono inizializzati con un dizionario letterale. Pertanto, possiamo ridurre lesempioprecedenteaquantosegue:varcpus=

    [BBCModelB:6502,Lisa:68000,TRS-80:Z80]

    Senoninizializzateundizionarioconunvaloreletterale,potetespecificareunacapacitminimausandoilcodiceseguente:vardictionaryName=[Type:Type](minimumCapacity:Int)

    varcpus=[String:String](minimumCapacity:5)

    Poterspecificareunacapacitminimapuessereutilepermigliorareleperformancedeidizionarichemutanofrequentemente.Adifferenzadegliarray,nonpotetedeterminarelacapacitdiundizionario,coscomenonpoteteriservareunacapacitaggiuntivadopolacreazione,permigliorareleperformance.

    EccoaltrecaratteristichedeidizionariinSwift.

    Tuttelechiaviinundizionariodevonoesseredelmedesimotipo.

    Tuttiivaloriinundizionariodevonoesseredelmedesimotipo.

  • Icontenutidiundizionariosonomemorizzatiinordinearbitrario.

    I dizionari sono un tipo di valore e vengono copiati quando sono assegnati opassati auna funzioneoaunmetodo (adifferenzadiNSDictionary, chevienepassatoperreference).

    AccedereaglielementideldizionarioPeraccedereaivalorideldizionariousatelachiavecomesotto-script,comemostratoqui:letcpu=cpus[BBCModelB]

    ProprietdeidizionariPoteteusarelefunzionalitcheseguonoperaccedereallevarieproprietdiundizionario:dictionaryName.isEmpty

    Boolean:true,seildizionariononhaelementi.dictionaryName.count

    Integer:ilnumerodicoppiechiave-valoreneldizionario.dictionaryName.keys

    Restituisceunarraycontuttelechiavineldizionario,chepoteteusareperiteraresulle chiavi in un dizionario (vedere Iterazioni sui dizionari a pagina 53). Lechiavirestituitenonhannoalcunordineparticolare.Perusarequestafunzionalitnelcontestodiunarray,dovetecopiarloinunnuovoarrayusandoquestasintassi:letnewArrayName=[Type](dictionaryName.keys)

    dictionaryName.values

    Restituisce un array di tutti i valori del dizionario, che possono essere usati periteraresuivaloridiundizionario(vedereIterazionisuidizionariapagina53).Lechiavirestituitenonhannoalcunordineparticolare.Perusarequestafunzionalitnelcontestodiunarray,dovetecopiarloinunnuovoarray,usandoquestasintassi:letnewArrayName=[Type](dictionaryName.values)

    ModificareundizionariomutabilePotetemodificareidizionarimutabilinelmodoseguente:dictionaryName[key]=value

    Imposta (o aggiorna) il valore dellelemento identificato da key. Per rimuoverequestacoppiachiave-valoredaldizionario,impostatevalueanil.dictionaryName.updateValue(newValue,forKey:key)

    Imposta (o aggiorna) il valore dellelemento identificato da key. Restituisce ilvecchiovalorecomeoptional(vedereOptionalapagina67),seeradisponibile.

  • dictionaryName.removeAll(keepCapacity:Bool)

    Rimuovetuttiglielementidaldizionario.LargomentokeepCapacityfacoltativoe ha valore predefinitofalse. Se impostato a true, la capacit del dizionarioresterimmutata.dictionaryName.removeValueForKey(key)

    Rimuoveunacoppiachiave-valoredaldizionario,identificatadakey.Restituisceilvalorechestatorimossoonilsenonerapresentealcunvaloreperkey.

    IterazionesuidizionariPer iterare su tutti gli elementi di un dizionario, potete usare un ciclo for-in, comemostratodiseguito:for(key,value)indictionaryName

    {

    }

    Analizziamoilfunzionamentoneidettagli:

    Il codice allinternodelle parentesi graffe viene eseguito unavolta per ciascunelementonellarray.

    Perciascunaesecuzione,keyevaluevengonoimpostatiallecoppiechiave-valoredeldizionario.Idizionarisonomemorizzatiinordinearbitrario.

    keyevaluesonocostantisebbeneilorovalorivenganomodificatiaciascunaiterazione,nonpossonoesseremodificatinelloop.

    Periteraresolosullechiavioivalorideldizionario,usateleproprietkeysovalues,cherestituisconounarraynonordinato:forvalueindictionaryName.values

    {

    }

    forkeyindictionaryName.keys

    {

    }

  • Funzioni

    InSwiftdichiaratelefunzioniusandolaparolachiavefunc,comemostratoquidiseguito:funcfunctionName(parameters)->returnType{body}

    Eccoalcunedellecaratteristichedellefunzioni inSwift,oltreaisuggerimentiper il lorouso:

    Lefunzionipossonoaverenessunoopiparametri.

    Senonesistonoparametri,leparentesivuotedevonocomunqueessereutilizzate.

    Lefunzioninondevonorestituireunvalore.

    Selafunzionenonrestituisceunvalore,omettetelafrecciaereturnType.

    TipideiparametriDi default, i parametri delle funzioni sono costanti (non possono essere modificati nelcorpo della funzione). I parametri variabili vengono creati facendo precedere al loronome,nelladichiarazionedellafunzione,laparolachiavevar,comemostratoqui:funcsomeFunc(vars:someType)->

    Poteteusarelavariabilescomevariabilelocaleemodificabilenelcorpodellafunzione.Iparametrivariabilevengonoperdutidopolarestituzionedellafunzione,quindinonpoteteusarliperpassaredeivaloriallesternodelcorpodellafunzione.

    Iparametriin-outvengonocreatifacendoliprecedere,nelladichiarazionedellafunzione,dallaparolachiaveinout,inquestomodo:funcsomeFunc(inouti:someType)->

    idiventaunaliasperunavariabileesternapassataperreference.Modificareiallinternodellafunzionemodificaanchelavariabileesterna.ComeperlereferencedellevariabiliinC++,doveteapporreuna&commerciale(&)primadelnomedellavariabilereferenziatainunachiamataaunafunzione:vari:Int=45

    someFunc(&i)

    RestituzionedivaloriopzionaliUna funzione pu restituire un valore opzionale. unmodo per indicare che non puessere fornito nessun valore valido di restituzione. Supponiamodi stare implementando

  • unafunzione(inutile!)pereseguireunafunzione.Ladefinizionedellafunzionepotrebbeiniziarecos:funcdivision(dividend:Double,divisor:Double)->Double

    {

    returndividend/divisor

    }

    possibileche ildivisoresiapariazero,cosacheprovocherebbeunerroredi runtime.Mediante la restituzione di un valore opzionale, possiamo indicare quando il risultato valido e quando non lo . Per specificare che un valore restituito opzionale, fateloseguiredaunpuntodidomanda.Lanostrafunzione,pertanto,diventacomesegue:funcdivision(dividend:Double,divisor:Double)->Double?

    {

    if(divisor==0){returnnil}

    returndividend/divisor

    }

    Se il divisore zero, restituiremo un valore nil; diversamente, potremo restituire ilrisultatodelloperazione.

    Poich ilvalore restituitooraopzionale,dobbiamotestarloprimadipoterlousare.Perfarlo,utilizziamoquestasintassi:vard=division(9.0,0.0)

    ifd!=nil

    {

    //ilvalorevalido

    println(d!)

    }

    else

    {

    //ilvalorenonvalido

    }

    Consultate anche le sezioni Optional a pagina 67 e Concatenamento di optional apagina70.

    RestituzionedipivaloriconletupleAveteunafunzionecherestituiscepidiunvaloregrazieallimpiegodiunatupla,comenellesempiochesegue:funcgetRange()->(lower:Int,upper:Int)

    {

  • return(someLowValue,someHighValue)

    }

    Poich i membri della tupla hanno i nomi assegnati nella dichiarazione della funzionedellesempioprecedente,possibileusarequestinomiperfarriferimentoaicomponentidopolachiamataallafunzione.Perquestomotivo,poteteaccedereaiduevaloriinquestomodo:letlimits=getRange();

    foriinlimits.lowerlimits.upper{}

    IltipodirestituzioneopzionaledellatuplaNeicasi incuiuna tuplavieneusatacome tipodi restituzionediuna funzione,potrestevoler indicare se la tupla stessa non contiene valori. Estendendo il precedente esempiogetRange(),potrebbecapitarechenonesistaunrangedivalorivalidiechequindinoncisianulladarestituire.Questasituazionepuesseregestitausandountipodirestituzioneopzionaleperlatupla,cheindicateapponendounpuntodidomandadopoleparentesicheidentificanoiltiporestituito,erestituendonil(anzichunatupla)seilrangenonvalido:funcgetRange()->(lower:Int,upper:Int)?

    {

    if(rangeIsNotValid){returnnil}

    return(someLowValue,someHighValue)

    }

    Perulterioriinformazioni,consultatelasezioneOptionalapagina67.

    NomidiparametrilocaliedesterniInomidiparametri,comep1nellesempiochesegue,agisconocomenomediparametrolocale,chevieneusatoallinternodelcorpodellafunzione.funcf(p1:Int){}

    Lentit che chiama la funzione fornisce un singolo valore integer come valore delparametro:leta=f(45)

    Perlefunzionichehannopiparametri,lospecificaredeinomidiparametriesterniaiutaachiarireilruolodiciascunparametro.Potetespecificareinomidiparametriesterninelmodoseguente:funcfuncName(externalNameinternalName:type,)

    funcsearch(strings:String,forStrings2:String)

  • ->Int{}

    Lafunzionediricercacosdefinita,verrquindichiamatanelmodoseguente:letopenDoor=

    search(string:userInput,forString:opensesame)

    Dove i nomi dei parametri esterni sono uguali, potete scrivere il nome una sola volta,apponendo ilprefisso#.Peresempio, ilcodicecheseguedefinisceforString siacomenomeinternosiacomeesternoperilsecondoparametro:

    funcsearch(strings:String,#forString:String)->Int{}

    Quandoinomideiparametriesternisonostatidichiarati,questinonsarannoopzionaliedovrannoessereusatinellechiamateperquellafunzione.Inaggiunta,inomiesterninonforniscono alcuna funzione di ordinamento arbitrario per i parametri. Per esempio, ilcodiceseguentenonverrebbecompilatousandolafunzionedefinitainprecedenza:

    letopenDoor=search(forString:opensesame,string:userInput)

    //erroredelcompilatore:Argumentstringmust

    //precedeargumentforString

    ValorideiparametrididefaultPeraggiungeredeivalorididefaultperqualunqueparametro,usateilcodicechesegue:

    funcsearch(strings:String,forStrings2:String=opensesame)->Int{}

    Se il parametro forString viene omesso in una chiamata alla funzione, comenellesempiochesegue,perquelparametroverrusatoilvaloredidefaultopensesame:letopenDoor=search(string:userInput)

    Seforniteaunparametrounvaloredidefaultsenzaunnomeesterno,Swiftgenererunnomeesternochecorrispondealnomelocale.

    ParametrivariadicUnparametrovariadicsupportaunnumerovariabiledivaloriininput.Potetespecificareunparametrovariadic facendo seguire al suonome trepunti di sospensione (), comedimostratodiseguito:funcsumOfInts(numbers:Int)->Int{}

    Lafunzioneverrebbequindichiamatanelmodoseguente:lettotal=sumOfInts(2,3)

    letanotherTotal=sumOfInts(5,9,11,13,22)

  • Nelcorpodellafunzione,ivaloripassaticomeargomentiallafunzionesonodisponibiliinunarray(inquestocasochiamatonumbers).

    Quandousateiparametrivariadic,dovetetenereinconsiderazionequantosegue:

    Unafunzionepuaveresolounparametrovariadic.

    Unparametrovariadicdevecompariredopotuttiglialtriparametri.

    TipidifunzioneIl tipo di una funzione unespressione del tipo dei suoi parametri in input e del suorisultato.Peresempio,per:funcsumOfInts(numbers:Int)->Int{}

    funcsearch(strings:String,forStrings2:String)

    ->Int{}

    funcdoesNothing(){}

    itipisono,rispettivamente:(Int)->Int

    (String,String)->Int

    ()->()

    Poteteusareitipidiunafunzioneinmoltiluoghiincuipoteteusareitipisemplici(comeInt).Peresempio,potetedichiarareunavariabileounacostanteinmodochesiauntipodifunzione,comemostratoqui:vargeneralPurposeFunc:(Int)->Int

    PotetequindiassegnarelavariabilegeneralPurposeFuncaunafunzionedellostessotipo:funcaddOne(i:Int)->Int{returni+1}

    funcaddTwo(i:Int)->Int{returni+2}

    generalPurposeFunc=addOne

    Quellavariabilepotrquindiessereusataquandoanchelafunzionepuessereusata:addOne(4)//restituisce5

    generalPurposeFunc(5)//restituisce6

    generalPurposeFunc=addTwo

    generalPurposeFunc(5)//restituisce7

    Potetepassaredelle funzioni comeparametri di altre funzioni, cos comedelle funzionipossonoessererestituitedaaltrefunzioni.Specificateiltipodellafunzionecomeiltipodiparametrooiltipodivalorerestituito.Lesempiocheseguedefinisceunafunzione,ilcuiunico parametro una funzione che accetta un integer come parametro e restituisce unvaloreinteger.Lafunzionedefinitanonrestituisceautonomamentealcunvalore:funcadaptable(inputFunc:(Int)->Int)->(){}

  • Lesempiosuccessivodefinisceuna funzionecheaccettaunsingoloparametro integererestituisce una funzione. La funzione restituita accetta un singolo parametro integer erestituisceunsingoloparametrointeger:funcselectOperation(i:Int)->(Int)->Int{}

  • Closure

    Da un punto di vista funzionale le closure sono simili aiblocchi inObjective-C e allelambdainlinguaggicomeScheme,C#ePython.

    Le closure sono funzioni anonime che possono essere passate come argomenti ad altrefunzioni(notecomefunzionidiordinesuperiore)orestituitedaaltrefunzioni.Possonofarriferimento a variabili e parametri dello scope in cui sono definite (sono a volte dettevariabiliesterne).Inquestocaso,sidicechestannocatturandoqueivalori(operazionedicloseover).

    Normalmente, definite una closure tramite una espressione closure, che ha il seguenteformato:{

    (parameters)->returnTypein

    statements

    }

    Perottenereunacomprensionemiglioredidovepossonorisultareutilileclosure,pensatealloperazione di ordinamento degli array. La libreria standard C offre una gamma difunzioni di ordinamento, una delle quali qsort(), che accetta come parametro unpuntatoreallafunzionediconfronto.Questafunzionediconfronto,definitadalchiamante,accetta come parametri due puntatori alle due entit che devono essere confrontate. Lafunzionediconfrontorestituisceunintegercheminoredi,ugualea,omaggioredizero,asecondachelaprimaentitsiaminoredi,ugualea,omaggioredellaseconda.

    Una closure rappresenta un metodo conciso per fornire una funzionalit simile, senzadoverdefinireunafunzionecheeseguailconfronto.Alcontrario,laclosurevienepassatacomeparametroinlineaallafunzionediordinamento.

    LalibreriastandarddiSwiftincludeunafunzione,sorted(),checreaunacopiaordinatadiunarray.Poteteusarlanelmodoseguente:letnames=[John,Zoe,Laura,albert,Allen]

    lets=sorted(names)

    //sora[Allen,John,Laura,Zoe,albert]

    SwiftsacomeconfrontareitipiintegraticomeString,InteFloat;perquestomotivopu ordinare gli array di questo tipo in ordine ascendente o alfabetico. Nellesempioprecedente,sorted() applica il suo comportamentodi default al tipoString eordina idati inmodoalfabetico(albertvienepostodopoZoeperch le lettereminuscole, inordinealfabetico,vengonodopoquellemaiuscole).

  • Esisteunaltraversionedisorted()cheaccettaunaclosurecomesecondoparametro.Laclosureprendeduevalori(dellostessotipo,comeilcontenutodellarray)edeverestituiretrueseilprimovaloredevessereordinatoprimadelsecondo(propriocomelafunzionediconfrontorichiestadaqsort(),descrittainprecedenza).Selarraychevieneordinatocontienedellestringhe,laclosuredevesseredefinitacomesegue:(String,String)->Bool

    Inaltreparole,laclosuredeveprenderedueparametriStringerestituireunvaloreBool,cheindicaseilprimodevessereordinatoprimadelsecondo.

    Eccocomedoveteinvocaresorted()efornireunaclosurechereplichiilcomportamentodellasempliceversionegidescrittaprima:lett=sorted(names,{(s1:String,s2:String)->

    Boolinreturns1

  • NomiautomaticidegliargomentiNelladiscussionesulleclosureabbiamodefinitoinostrinomiperfarriferimentoaciascunargomento richiestodalla closure stessa.Per esempio,perordinareunarraydi stringhe,abbiamoassegnatoinomis1es2agliargomenti,inmododapotervifareriferimentoinseguitonellespressionediconfronto:letu=sorted(names,{s1,s2ins2Bool

    Sono presenti due parametri stringa e Swift crea degli alias per i loro argomenti,chiamandoli$0 e$1. Luso di questi alias significa che non dobbiamo necessariamentedefinirlinoi,elesempiodellaclosuresorted()siriduceulteriormenteaquantosegue:lett=sorted(names,{$0

  • restituitedallastessafunzionechelecontiene,ilchesignificacheunaclosurepuessereeseguitadopocheivaloriaiqualifariferimentosonouscitidalloscope.

    Questasituazionenonportaaunerroredi runtime.Sidiceche laclosurecatturaquestivalorieneestendeilciclodivitaoltreloscopenelqualesonostatidefiniti.

    Nellesempiochesegue,unafunzione(makeTranslator)creanuovefunzioni(closure)elerestituiscecomerisultato.Prendeunsingoloargomento(unastringa)conilnomelocalegreeting. La funzione che viene restituita accetta un singolo parametro (una stringa) erestituisceunaltrosingoloparametro(unastringa):funcmakeTranslator(greeting:String)->(String)->String

    {return

    {(name:String)->Stringin

    return(greeting++name)}}

    Le closure che vengono create da questa funzione catturano il valore della stringagreetingelousanoinseguito,ogniqualvoltaverrannoeseguite,anchesetalevaloreormaifuoriuscitodalsuoscope.

    Eccocomepoteteusarequestafunzione:varenglishWelcome=makeTranslator(Hello)

    vargermanWelcome=makeTranslator(GutenTag)

    Dopo aver eseguito questo codice, englishWelcome far riferimento a una closure cheaccettaunsingoloargomentostringae lorestituircon laparolaHellocomeprefisso,mentregermanWelcomefarriferimentoaunaclosurecheaccettaunsingoloargomentoelorestituirconleparoleGutenTag.

    PoichenglishWelcomeegermanWelcome fannoriferimentoadelleclosure,e leclosuresono funzioni, possiamo invocarle nello stessomodo in cui chiamiamo qualunque altrafunzione:englishWelcome(Bill)

    //restituisceHelloBill

    germanWelcome(Johan)

    //restituisceGutenTagJohan

    Leclosureeivalorichequestehannocatturatorimarrannodisponibilifinchlevariabiliallequalifannoriferimentoandrannofuoriscopeoverrannoimpostateconnuovivalori.Peresempio,secambiamoladefinizionedienglishWelcomeinquestomodo:englishWelcome=makeTranslator(Gday)

    englishWelcome(Bruce)

  • //restituisceGdayBruce

    allora la memoria allocata dalla versione Hello della closure (con i relativi valoricatturati)verrrilasciata.

    CatturadeivaloriperreferenceNella discussione precedente, il valore catturato (the greeting string value) vieneeffettivamentecopiatoquando laclosurevienecreata,perchquelvalorenonvienemaimodificatodallaclosurestessa.

    I valori che una closure modifica non vengono copiati ma sono invece copiati perreference.Eccounesempiorivisto,chetieneilconteggiodelnumerodivolteincuivienechiamato:

    funcmakeTranslator(greeting:String,personNo:String)->(String)->String{

    varcnt=0

    return{

    (name:String)->Stringincnt++return(greeting++name+,+

    personNo+\(cnt))}}

    Inseguito,creiamoduenuoveclosurepergenerareunsaluto:

    vargermanWelcome=makeTranslator(GutenTag,SiesindNummer)

    varaussieWelcome=makeTranslator(Gday,yourenumber)

    Equindipossiamochiamarle:germanWelcome(Johan)

    //restituisceGutenTagJohan,SiesindNummer1

    aussieWelcome(Bruce)

    //restituisceGdayBruce,yourenumber1

    aussieWelcome(Kylie)

    //restituisceGdayKylie,yourenumber2

    Ciascunaclosurememorizzaunareferenceacnt,cheunavariabilelocalenellafunzionemakeTranslator().Nelfarlo,questeestendonoilciclodivitadiquellavariabile locale,facendolacorrispondereallavitadellaclosure.

  • Notatecheciascunaclosurecontinuaadaverelapropria istanzadicnt,perch,difatto,esistonoduediverseistanzeseparateperledueesecuzionidimakeTranslator.

  • Optional

    Glioptional di Swift forniscono un mezzo per indicare lesistenza di un valore, senzausurparealcunapartedeipossibilistatiinerentiilvalorestesso.

    Per esempio, unapplicazione potrebbe voler registrare se una porzione di stringa siapresentenelmondofisicoe,secos,registrarelalunghezzadiquellapartedistringa.Inquestoesempio,unvalorenegativo(come-1)puessereusatoperindicarechelastringanonpresente,perchquestotipodivalorenonpotrebbemairappresentareunalunghezzaeffettiva.Questoesempiousaunasingolamemorizzazioneperrappresentareselastringapresentee(soloselo)qualelunghezzaabbia.

    Spesso, in Objective-C viene usata una tecnica simile, nella quale gli oggetti (o, piprecisamente,ipuntatoriaglioggetti)possonoesserenil,aindicarechenonesistealcunoggetto.MoltedellechiamateaimetodidiObjective-Crestituiscono(unpuntatorea)unoggettoonil,selachiamataalmetodofallitaosesisonoverificatialtrierrori.

    InSwift,iriferimentiaglioggettinonsonopuntatorienormalmentenonpossonoessereimpostatianil,amenochenonvenganospecificamentedichiaraticomevalorioptional.Eccounesempiodellasintassiperquestotipodidichiarazione:varstr:String?

    Ilpuntodidomanda,chesegueimmediatamenteiltipo,dichiarachelavariabilestrunoptional.Ilsuovalorepuesistereononesistere.Ilnonavereunvalorenonhalostessosignificato del caso in cuistrmemorizzi una stringa vuota (quando un nuovo optionalvienecreatoinquestomodo,ilsuovaloreinizialeimpostatoanil).

    Quandounavariabilevienedichiaratacomeoptional,deveessereusatainpuntiincuisiaconsentitolusodiuncontestooptionalodeveessereunwrapped(consultatelasezioneUnwrappingdeglioptionalinquestapagina)perrivelareilvaloresottostante.

    Per esempio, potete assegnare un optional a un altro optional senza problemi, comemostratoquidiseguito:varn:String?

    n=str

    Tuttavia,nonpoteteassegnarloaunnon-optional:varr:String

    r=str//produrrunerroreinfasedicompilazione

    Poichrnonunoptional,ilcompilatorenonconsentirchevengaassegnato.

    Seunvaloreoptionalesistegi,assegnarglinilrimuovertalevalore:

  • str=nil

    Ilvalorenilassegnabileinquestomodosoloaglioptional.Tentarediassegnarenilaunavariabilenon-optionaloaunacostanteprodurrunerroreinfasedicompilazione.

    UnwrappingdeglioptionalPeraccederealvalorememorizzatoinunoptional,primaverificateseilvaloreesisteconladichiarazioneif.Seesiste,usateilpuntoesclamativoperforzarelunwrapdelloptionaleaccederealdatogrezzomemorizzato,comevienedimostratoquidiseguito:ifstr//controllaseloptionalhaunvalore

    {

    r=str!//eseguelunwrapelocopia

    }

    else

    {

    //loptionalnonhavalore

    }

    Forzare lunwrapping di un optional per un valore inesistente provocher un errore diruntime.

    OptionalconunwrapimplicitoInalcunesituazionipotrebbeessereappropriatolusodiunoptional,ancheseavrsempreunvalore.Peresempio,unoptionalcreatousandoletnonpuesseremutato(quindinonpu essere impostato a nil) e devessere inizializzato quando dichiarato, quindi nonpotrmainonavereunvalore:letconstantString:String?=Hello

    Anche se il suovalorenonpucambiare,perpoterlousare inuncontestonon-optionaldovrcomunqueessereoggettodiunwrapping:varmutableString:String

    mutableString=constantString//erroreincompile-time

    mutableString=constantString!//consentito

    Perquestoealtriusi,Swiftoffreglioptionalconunwrapimplicito,chevengonodefinitiusando un punto esclamativo dopo il tipo, anzich un punto di domanda. Dopo averlodefinito,unriferimentoalvalorediunoptionalnondeveessereoggettodiunwrapping:questoavverrautomaticamenteognivoltacheverrreferenziato:letconstantString:String!=Hello

    mutableString=constantString

    Questoesempioartificioso,maglioptionalconunwrappingimplicitogiocanounruolo

  • importante durante linizializzazione di una classe. Consultate la sezione Classi, apagina87,perulterioriinformazioni.

    BindingdeglioptionalIlBindingdeglioptionalunmodoperverificareseunoptionalpossiedeunvaloree,secos,creareunacopianon-optionalperlusoinunadichiarazioneif.Lasintassi,chenonapparecertonaturalemachepotrebbediventarelasecondanaturadeglisviluppatoriSwiftpinavigati,hailseguenteaspetto:ifletsomeConst=someOpt

    {

    // someConst ora una versione unwrapped di someOpt println(someConst)

    }

    IpotizzandocheloptionalsomeOptabbiaunvalore,someConstdetieneunacopiadiquelvaloreallinternodelleparentesigraffedelladichiarazioneif.PoichsomeConstnonunoptional, ilsuovalorepuessereusatodirettamente lunwrappingstatogestitodalladichiarazionelet.

    Usatevaralpostodiletpercreareunacopiaunwrappeddelloptionalchesiamutabile.La modifica del valore copiato in questo modo non modifica il valore delloptionaloriginario.

    ConcatenamentodioptionalQuando accedete a un optional, questo ha un valore o nil, e dovete verificare che ilvaloreesistaprimadieseguirelunwrapping,comenellesempioseguente:vars:String?

    ifs//verificaseloptionalhaunvalore

    {

    varr=s!//faqualcosacontalevalore

    }

    else

    {

    //loptionalnonhaunvalore

    }

    Poteteusareglioptionalinogniistante,aprescinderedalfattocheunvaloreesistaononesista:

    Laproprietdiunaclasse,strutturaoenumerationpucontenereilvalorediunoptional.

  • Unmetododiunaclasse,unastrutturaoenumerationpurestituireilvalorediunoptional.

    Unsubscriptdiunaclasse,unastrutturaoenumerationpurestituireunvaloreoptional.

    NOTAQuestocontenutocomparequicomesefosseinerenteglioptional,malargomentoegliesempiusatiper illustrarlorichiedonoanchela comprensione delle classi (vedere Classi a pagina 87), dellestrutture (consultare Strutture a pagina 113) e dei subscript(vedereSub-scriptapagina99).

    Ilconcatenamentodioptionalunserviziograziealqualepoteteinterrogareunoptional,oqualcosachehaunvaloreedipendedaunoptional,senzadovertestarespecificamenteloptionalstesso.Usateilconcatenamentodeglioptionalquandoaccedetealleproprietdiunaclasse,unastrutturaoenumeration,ametodioasubscriptusandolasintassibasatasulpunto.

    Considerate questo semplice esempio di due classi, in cui la classe A contiene unareferenceoptionalaunistanzadellaclasseB:

    classA{

    varotherClass:B?}

    classB{

    varsomeProperty:Int=7funcsomeMethod(){

    println(someMethodcalled!)}subscript(index:Int)->String{

    get{returngetterfor[\(index)]called}set{}}}

    Ora, ipotizziamo di avere una reference optional di unistanza della classe A, comenellesempiochesegue:vara:A?

    Ipotizziamo anche di voler seguire il percorso dalla nostra reference optional a fino a

  • someProperty o someMethod() della classe B. Senza il concatenamento degli optionaldovremmo verificare che ciascun optional possieda un valore; solo se cos, possiamoscendereallivellosuccessivo,comenelseguentecodice:

    ifa!=nil{

    ifa!.otherClass!=nil{

    println(a!.otherClass!.someProperty)}else{

    println(nopropertyavailable)}}else{

    println(nopropertyavailable)}

    Questoportaaverifichecondizionalipotenzialmentemoltoprofonde,valeadirepropriocicheilconcatenamentodeglioptionalsemplifica.Grazieaquestoconcatenamento(ealbindinglet),poteteridurreilcodiceaquantosegue:ifletp=a?.otherClass?.someProperty

    {

    println(p)

    }

    else

    {

    println(nopropertyavailable)

    }

    Seunoqualunquedeglioptionalnellacatenarestituisceunvalorenil,linteraespressionerestituirnil.

    Luso del concatenamento di optional non ristretto alla sola lettura dei valori dellepropriet.Possiamoanchescriverleinquestomodo:a?.otherClass?.someProperty=6

    La dichiarazione restituir nil se lassegnazione fallisce perch una delle parti dellacatenadioptionalharestituitonil,cosachepuessereverificatainquestomodo:if(a?.otherClass?.someProperty=6)==nil

    {

    //unabletowritetheproperty

  • }Potetechiamareimetodiusandoilconcatenamentodioptional,nelmodoseguente:a?.otherClass?.someMethod()

    Dinuovo, la chiamataalmetodo restituirnil se la chiamata stessa fallisseperviadelfattocheunadellepartidellacatenaharestituitonil.Anchese,normalmente,ilmetodorestituisce un valore non-optional, verr sempre restituito come optional quando vieneusatonelcontestodiunacatena.

    Poteteancheusareilconcatenamentodioptionalconisub-script:a?.otherClass?[1]

    //restituiscenilogetterfor[1]called

    a?.otherClass?[3]=Optionalchainingisneat

    //restituiscenilselassegnazionefallisce

  • Flussodelprogramma

    Swiftincludelanormaleselezionediloop(cicli)edifunzionidiesecuzionecondizionale.Quasi tutti questi sono superficialmente identici alle controparti presenti nei linguaggisimili al C, ma in certi casi (per esempio la dichiarazione switch) offrono dellefunzionalitmoltopiesteseesicure.

    LoopSwift dispone dei costrutti standard per i loop che vi aspettereste di trovare in unlinguaggiodiprogrammazione,incluselevariantifor,whileedo-while.

    Loopfor-condizione-incrementoIl loop for-condizione-incremento dal punto di vista funzionale ilmedesimodel ciclofor in C. Il loop consiste in una fase di inizializzazione, un test, un incremento e uninsiemedidichiarazionichevengonoeseguiteperciascunaiterazionedelloop.Ecconeunesempio:forinizializzazione;condizione;incremento

    {

    dichiarazioni

    }

    Letrefasifunzionanoinquestomodo:

    Lafasedi inizializzazionedefiniscelecondizioniper lavviodel loop(disolitoinizializzandouncontatoreperilloop).

    Lacondizioneverificaseilmeccanismoditerminedel loopstatoraggiuntoognivoltachequestougualeatrue,ledichiarazioninelcorpodelloopvengonoeseguiteunavolta.

    Lafasediincrementomodificaunavariabileounvalorechecostituisceunapartedel testcondizionale,perassicurarsichepossaessereraggiunta lacondizionediarresto(disolitoincrementandoilcontatoredelloop).

    possibilecheledichiarazioninelcorpodelloopnonvenganomaieseguite.Affinchcisucceda,lacondizionedovrebberisultarefalsealmomentodellaprimaesecuzione.

    Il corpo del loop definisce un nuovo scope, nel quale possono essere definite variabililocaliecostanti.Questeandrannofuoriscopenonappenaillooptermina,facendoperdereirelativivalori.

  • Laversionepifamiliarediquestoloopdovrebbeesserequellachetrovatequisotto:forvari=0;i
  • //i386

    Lesempiosuccessivoiterasuicontenutidiundizionario.Comeindexdelloopvieneusataunatupla,quindiperciascunaiterazioneotterremolachiaveeilvaloreassociato(vedereanchelasezioneIterazionesuidizionariapagina53):varvehicles=[bike:2,trike:3,car:4,lorry:18]

    for(vehicle,wheels)invehicles

    {

    println(vehicle)

    }

    //stampa:

    //car

    //lorry

    //trike

    //bike

    Lesempio precedente dimostra anche che i dizionari sono memorizzati in ordinearbitrario.

    LoopwhileComeperilC,icicliwhileverificanounacondizioneprimadiverificareilcorpodelciclostesso;questultimovieneeseguitosoloselacondizioneequivaleatrue.

    Ilformatostandardilseguente:whilecondizione

    {

    dichiarazioni

    }

    Potete usare il loop while per replicare le funzionalit di un ciclo forcondizione-incremento,comenelcodiceseguente:varcount=0;

    while(countInt{}

    Ciincontrastoconledefinizionideimetodi,dovedidefaulttuttiinomideiparametri,tranne ilprimo,sonosialocalisiaesterni.Ilprimonomediparametrolocale,amenochenonsiaprecedutodalnomediunparametroesternoodalcarattere#.

    Questa differenza di comportamento predefinito tra funzioni e metodi incoraggia lascritturadelledefinizionidimetodiinSwift,chevengonochiamatiinmodomoltosimileallostileimpiegatoperlechiamateaimetodidiObjective-C.

    Consideratequestoesempio, che introduceunanuovaclasse riguardante le stringheconunafunzionediricerca:classSomeStringClass

    {

    funcsearchFor(searchString:String,startingAt:Int)->Int

    {

    //restituisceilrisultatodellaricerca

    }

    }

    NelmetodosearchFor()definitoinquestaclasse,searchStringunnomediparametrolocale,mentrestartingAtunnomesialocalesiaesterno.Lafunzionefacilitalaricerca

  • diunistanzadellaclassestringa,grazieallimpiegodiquestasintassi:varhaystack=SomeStringClass()

    haystack.searchFor(needle,startingAt:0);

    Entriamoneidettagli:

    Sevoletecheilprimoparametroabbiaunnomeesterno,dovetefarprecederealnome locale un nome esternoo anteporre al nome locale il carattere #, cos dapoterlousarecomenomeesterno.

    Per il secondo parametro e i seguenti, se volete prevenire la definizione di unnomeesterno,fateprecedereilcarattere_(underscore)atalenomelocale.

    Per ilsecondoparametroe iseguenti,sevoletedefinire ilvostronomeesterno,anteponetealnomelocaleilnomeesternodesiderato.

    SelfOgniistanzadiunaclasse(ealtritipi)disponediunaproprietgenerataautomaticamenteechiamataself,chefariferimentoallastessaistanza.ConsideriamounaversioneestesadellanostraclasseRect:

    classRect{

    varx=0.0,y=0.0varwidth=0.0,height=0.0funcarea()->Double{

    returnwidth*height}funcsameSizeAs(width:Double,_height:Double)->Bool{

    returnwidth==self.width&&height==self.height}}

    Nelmetodoarea(), siawidth siaheight sono propriet dellistanza e la dichiarazionereturnavrebbepotutofareriferimentoinmodoesplicitoaquestedueproprietinquestomodo:returnself.width*self.height

    Questo per non necessario perch nelle chiamate aimetodiself vienenormalmenteconsideratoognivoltachevengonousateleproprietdiquellaclasse.

    Leccezionesiverificaquandounnomediunparametroperunmetodougualealnomedellaproprietperlaclasse,comenelcasodelmetodosameSizeAs().Neimetodi,inomideiparametrihannolaprecedenzasuquellidellepropriet;perquestomotivo,selfdeveessereusatoinmodoesplicitoperdifferenziareleproprietwidtheheightdaiparametri

  • widtheheight.

    DefinizionedeimetoditipoQuando definite unmetodo tipo per una classe, dovete far precedere la definizione delmetododalleparolechiaveclassfunc,comenellesempioseguente:

    classAClass{

    classfuncaTypeMethod(){

    //implementazione}}

    Nonostanteleapparenze,nonsitrattadelladefinizionediunaclasseannidata.

    Perinvocareunmetodotipoperunaclasse,fateloprecederedalnomedellaclasse,usandolasintassipuntata:AClass.aTypeMethod()

    Per invocare lo stesso metodo dallinterno di altri metodi definiti per la classe, poteteomettereilnomedellaclasse,perchlequivalentediself.

    Unmetodo tipo pu accedere ad altri tipi dimetodi definiti nella classe, oltre che alleproprietditipodefinitenellaclassestessa.

    Sub-scriptInSwiftpotetedefiniredeimetodisub-scriptperlevostreclassi,cosachevipermettediusarelasintassisub-scriptper leggereescrivereivaloriappropriatiperunistanzadellavostraclasse.

    La sintassi sub-script il modo in cui normalmente accedete ai membri di array edizionari,comevienedimostratoquidiseguito:

    varm=[Int](count:10,repeatedValue:0)m[1]=45;m[2]=m[1]*2

    varcpus=[BBCModelB:6502,Lisa:68000,TRS-80:Z80]letcpu=cpus[BBCModelB]

    La sintassi sub-script permette sia la lettura sia la scrittura dei valori, e aderisce alseguentepatterngenerico:

    classSomeClass

  • {subscript(index:someIndexType)->someReturnType{

    get{

    //restituiscesomeReturnTypeinbaseaindex}set(valueName){

    //scrivevalueNameinbaseaindex}}}

    Potete omettere il nome del parametrovalueName, nel cui caso il parametro oggetto discritturapotressereraggiuntocomenewValue.

    Eccounaclassediesempiocherappresentaivaloriinbyte.definitoancheunmetodosub-script,medianteilqualepoteteaccedereaisingolibit,poichilbyteunarraydibit:

    classByte{

    vard:UInt8=0

    subscript(whichBit:UInt8)->UInt8{

    get{return(d>>whichBit)&1}set{

    letmask=0xFF^(1

  • Per un sub-script in sola lettura, omettete la definizioneset in questo caso,poteteancheometterelaparolachiavegeteridurreilcorpodelsub-scriptalsolocodiceessenzialepercalcolareerestituireilvalorenecessario.

    Iparametrideisub-scriptsilimitanoaisingolivaloriinteger;potetedichiarareunmetodosub-scriptcheaccettiqualunquenumerodifloat,stringheoaltritipichesoddisfinoivostrirequisiti.

    Potete definire metodi sub-script overloaded, fin tanto che questi accettanodiversi numeri e/o tipi di parametri, o restituire diversi tipi di valore. Swiftdeterminerilmetodoappropriatodainvocareusandolinferenzadeitipi.

    ProtezionedeimembriSwiftfornisceunmeccanismoperilcontrollodellaccessoapropriet,metodiesub-scriptdelleclassi,comepartediunpiampiosistemadicontrollodegliaccessi.ConsultatelasezioneControllodiaccessoapagina127perulterioriinformazioni.

    Ereditariet:derivareunaclassedaunaltraPotete definire nuove classi sulla base di quelle esistenti.Quandoquesto viene fatto, sidicechelanuovaclasseereditatutteleproprieteimetodidellaclasseesistente;lanuovaclassequindiderivatadaquellaesistente.

    Unesempio tipicoper illustrare lereditariet datodalle formegeometriche in2D.Laclasse base generica contiene metodi e propriet che devono essere comuni a tutte leforme, come il colore, il riempimento, lo spessore della linea e, probabilmente, anchelorigineo il rettangoloche la racchiude.Leclassiderivate includono leeffettive formegeometriche, come linee, cerchi, ellissi, quadrati, poligoni e cos via.Ognuna di questeintroduce nuovi metodi e propriet che sono specifiche a quella data forma (come unmetodo per il disegno e propriet per memorizzare i dettagli geometrici), ma tutteereditanodallaclassebaseilsetdiproprietemetodicomunichetutteleformehanno.

    InSwift,potetederivareunaclassedaunaltrausandoquestasintassi:classNewClassName:BaseClassName

    {

    //definizionidimetodieproprietperlanuovaclasse

    }

    OverridingdelleentitsuperclasseQuandounaclassevienederivatadaunaltra,lanuovaclassevienechiamatasottoclasse,mentrequelladallaqualequestaderivatasichiamasuperclasse.Sebbenenellamaggiorpartedeicasi auna sottoclasseverrannoaggiunteproprietemetodi specifici rispettoaquellipresentinellasuperclasse,unasottoclassehaanchelacapacitdieseguireloverride

  • (lasovrascrittura)deimetodiedelleproprietdellasuperclasse,difattoridefinendoli.

    Pereseguireloverridediqualcosachegidefinitoinunasuperclasse,doveteprecedereladefinizionedellasottoclasseconlaparolachiaveoverride.Questounsegnaleperilcompilatore di Swift che la ridefinizione intenzionale e che non avete creatoaccidentalmenteunmetodoounaproprietconilmedesimonome.

    InSwiftpoteteeseguireloverridedimetodi,proprietesub-script.

    AccederealleentitsovrascrittedellasuperclasseUna classe derivata pu usare il prefisso super nelle definizioni delloverriding peraccedereallaversionedellasuperclassediquellentit.Quisottosono illustrati imetodichepoteteusareperottenerequestorisultato:

    Peraccedereaunmetodosovrascritto,chiamateloconsuper.methodName().

    Per accedere a una propriet sovrascritta, fate riferimento a questultima consuper.propertyNamenelgetter,nelsetterodelledefinizionidellosservatore.

    Peraccedereaunsub-scriptsovrascritto,usatesuper[indexValue].

    ProprietdelloverridingNonpotete sovrascrivereunaproprietdi una superclasse con lavostra stessapropriet(nonavrebbesensoduplicarelospaziodimemorizzazione),mapoteteeseguireloverridediunaproprietaffinchforniscaivostrigetteresetterpersonalizzatiper listanzadellasuperclasse,oppureaggiungereunosservatoredellapropriet,inmodochepossiateessereinformatiquandoivalorivengonomodificati.

    NellepagineprecedentiabbiamointrodottolaclasseRect,permemorizzaredeirettangoli.Lesempio che segue crea una classe derivata, Square(), che esegue loverride dellepropriet width e height con nuovi getter e setter. Questi assicurano che laltezza e lalarghezzacorrispondanosempreeperquestoleistanzedellaclasseSquarerappresentanosempredeiquadrati:

    classSquare:Rect{

    overridevarwidth:Double{

    get{returnsuper.width}set{

    super.width=newValuesuper.height=newValue}}overridevarheight:Double{

  • get{returnsuper.height}set{

    super.width=newValuesuper.height=newValue}}}

    Notate che il getter e il setter accedono ancora alle propriet memorizzate nellasuperclasse,graziealprefissosuper.Eccounesempiodellaclasseinuso:vars=Square()

    s.width=20.0

    s.height=10.0

    s.area()

    //restituisce100.0

    s.width

    //restituisce10.0(not20.0)

    Quandoeseguiteloverridingdellepropriet,noteretequantosegue:

    Potete sovrascrivere le propriet ereditate in sola lettura e quelle in lettura escrittura,definendosiaungettersiaunsetter.

    Non potete eseguire loverriding delle propriet ereditate in lettura e scrittura,trasformandoleinsolalettura.

    Seforniteunsetter,dovreteanchefornireungetter (anchesequestorestituiscesololeproprietnonmodificatedellasuperclasse).

    Potete sovrascrivere le proprietmutabili ereditate (dichiarate convar) congliosservatori delle propriet,ma non potete sovrascrivere le propriet immutabiliereditate (dichiarate con let) in questo modo (perch gli osservatori delleproprietsonoutiliperosservarelascritturacheinteressalapropriet).

    Nonpotete sovrascrivereunapropriet siaconunsetter siaconunosservatore(perchilsetterpuagireanchecomeosservatore).

    Overridingdimetodiesub-scriptPer eseguire loverriding di unmetodo o sub-script gi esistente nella superclasse, fateprecedereilnomedellelementonellaclassederivatadallaparolachiaveoverride.

    Nella precedente discussione sui sub-script abbiamo introdotto la classe Byte, cheincludeva unmetodo sub-script che ci permetteva di accedere a ciascun bit di un byte,trattandolocomeunarraydibit,propriograzieallasintassisub-script.

    Unproblemaimportante,relativoaquestaclasse,chequestanoneseguealcuncontrollo

  • dei limiti sul valore del sub-script o di quello che devessere scritto. Se facessimoriferimento a una posizione in bitmaggiore di 7, il programma terminerebbe, perch lamascheradiassegnazionenelsettergenererebbeunoverflow.Seassegnassimounvaloreinbitdiversoda0o1,lassegnazioneavrebbeluogo,macreerebbeproblemiaglialtribitnellaproprietchestiamopresentandocomearraydibit.

    Ascopopuramenteillustrativo,creiamounaclassederivatapisicura,chesovrascrivaladefinizione subscript in modo da assicurarci che questi valori non possano eccederequelliappropriati:

    classSafeByte:Byte{

    overridesubscript(whichBit:UInt8)->UInt8{

    get{returnsuper[whichBit&0x07]}set{super[whichBit&0x07]=newValue&1}}}

    Notatechequestocodiceusaancoralimplementazionedellasuperclasseperlafunzionesub-script:vengonosolamenteripulitiilvaloreinbitelarelativaposizione.

    PrevenireloverridingeilsottoclassamentoAnteponendolaparolachiavefinalalladefinizionediunapropriet,diunmetodoodiun sub-script, poteteprevenirequesta entitdalloverriding inunaclassederivata.Eccouna versione modificata della nostra classe Rect, che usa la parola chiave final perimpedirecheleproprietwidtheheightsianooggettodioverriding:

    classRect{

    varx=0.0,y=0.0finalvarwidth=0.0,height=0.0//restodelladefinizione}

    Notatechelusodifinal inquestocontestononsignificacheivaloridiwidtheheightsiano bloccati; significa solo che le propriet non possono essere sovrascritte in unasottoclasse.

    Questamodifica implicache lanostraclasseSquare,presentatanellepagineprecedenti,nonpossapiesserecompilata,perchcercadisovrascriverequesteproprietconsetteregetterpersonalizzati.

    Potete anche usare la parola chiave final davanti alla definizione di una classe, perimpedirechesiaoggettodisottoclassamento.

  • InizializzazioneLinizializzazione il processodi configurazionedeivalori appropriati di default per lepropriet memorizzate in una nuova istanza di una classe, struttura o enumeration. Ilprocedimento simile a un costruttore in C++, C# o Java, oppure al selettore Init inObjective-C, e assicura che una nuova istanza sia pronta per luso e non contenga daticasualiononinizializzati.

    Linizializzazione avviene automaticamente per una nuova istanza di una classe; nondovetechiamareesplicitamentelinizializzatore,sebbenedobbiatechiamarequellidiunasuperclasse tramite gli inizializzatori di una classe derivata (consultate la sezioneInizializzazioneedereditariet,apagina110,perulterioriinformazioni).

    Potete inizializzare le propriet memorizzate provvedendo allassegnazione di valori didefaultvaluesnelladefinizionedellaclasse,oppuredefinendounaopifunzioniinit()nella classe. La classe Byte, che abbiamo introdotto in precedenza, dimostralinizializzazioneperassegnazione:classByte

    {

    vard:UInt8=0

    //restodelladefinizionedellaclasse

    }

    Per le classi pi complesse, prassi comune scrivere una o pi funzioni init(), pergestireilprocedimentodiistanziamentodinuoveistanzediunoggetto.Perleclassi,Swiftsupporta due tipi di funzione di inizializzazione: gli inizializzatori designati e gliinizializzatoridiconvenienza.

    Un inizializzatore designato deve inizializzare tutte le propriet di una classe. In unasottoclasse, deve inizializzare tutte le propriet definite in essa e quindi invocare uninizializzatore designato nella superclasse per continuare il processo di inizializzazionepertutteleproprietereditate.

    Un inizializzatore di convenienza fornisce un modo per chiamare un inizializzatoredesignato,conalcunideirelativiparametriimpostatiaivalorididefault.

    Uninizializzatoredesignatovienedefinitousandolasintassiseguente:

    classClassName{

    init(parameterList){

    //dichiarazioniperinizializzarelistanza}

    //restodelladefinizionedellaclasse}

  • Uninizializzatorediconvenienzavienedefinitoconlasintassiseguente:

    classClassName{

    convenienceinit(parameterList){

    //dichiarazioniperinizializzarelistanza}//restodelladefinizionedellaclasse}

    Nellelenco che segue, trovate alcune importanti caratteristiche relative al processo diinizializzazione:

    Seunaproprietdisponediunosservatoredipropriet,taleosservatorenonvieneinvocatoalmomentodellinizializzazione.

    Leproprietditipooptionalsonoautomaticamenteinizializzateanil,senonleinizializzateinmodoseparato.

    Lepropriet immutabili (dichiarateconlet)possonoesseremodificatedurantelinizializzazione, anche se vi stato assegnato un valore di default nelladefinizionedellaclasse.

    Un inizializzatore designato occupa un ruolo principale per una classe. Lamaggior parte delle classi ne avr uno solo, ma ne sono concessi altri: peresempio,unosenzaargomenti,cheimpostitutteleproprietaivalorididefault,eunoconargomenti,cheservaainizializzareivaloriperproprietspecifiche.

    Uninizializzatoredesignatodevechiamareuninizializzatoredesignatoperlasuasuperclasse.

    Gli inizializzatori di convenienza sono facoltativi e secondari; questi devonochiamarealtriinizializzatorinellastessaclasse.

    Lesecuzionediun inizializzatorediconvenienzadeveportareallesecuzionediuninizializzatoredesignato.

    Swiftsupportaancheideinizializzatori,chevengonoinvocatiautomaticamenteprimacheunoggettovengadeallocato(consultarelasezioneDeinizializzazioneapagina111perulterioriinformazioni).

    InizializzatoridesignatiLa nostra classe Rect mostrava linizializzazione tramite assegnazione allinterno delladefinizione:

    classRect{

    varx=0.0,y=0.0

  • varwidth=0.0,height=0.0//restodelladefinizione}

    Possiamo riscriverla usando invece una funzione per un inizializzatore designato, inquestomodo:

    classRect{

    varx,y,width,height:Doubleinit(){

    x=0.0;y=0.0width=0.0;height=0.0}//rimanenzadelladefinizionedellaclasse}

    Questainit()didefault, senzaparametri, linizializzatore cheviene chiamatoquandocreateunnuovooggettosenzaparametridiinizializzazione,comenelcodicechesegue:varq=Rect()

    Potetecreare inizializzatoriaggiuntivi,ciascunodeiqualiaccettaundiversonumeroe/otipodiparametri.LaversioneestesacheseguedellaclasseRectincludeduediversitipidimetodi per inizializzatori designati, i quali verranno chiamati a seconda di come Rectvieneistanziata:

    classRect{

    varx,y,width,height:Doubleinit(){

    x=0.0;y=0.0width=0.0;height=0.0}

    init(x:Double,y:Double,width:Double,height:Double){

    self.x=xself.y=yself.width=widthself.height=height}}

    Orapossibileusarediversimetodiinit()percreareleistanzediRect:varq=Rect()

  • varr=Rect(x:2.0,y:2.0,width:5.0,height:5.0)

    Notate che la seconda funzione init() possiede nomi di parametri definiti solointernamente,malistanziamentodirmostrachequestisonovisibiliancheesternamente.

    NOTAPer le funzioni init(), Swift generer sempre un nome diparametro esterno, se rilever che non ne stato definito alcuno.Inoltre, i nomi di parametri esterni (che siano definitiesplicitamente o generati in modo implicito) devono essere usatiquandolaclassevieneistanziata.

    Sevoleteimpedirelagenerazionediunnomediparametroesterno,fateprecedereilnomedelparametrointernodaununderscore,comevienemostratonelcodicechesegue:

    classRect{

    varx,y,width,height:Doubleinit(){

    x=0.0;y=0.0width=0.0;height=0.0}

    init(_x:Double,_y:Double,_width:Double,_height:Double){

    self.x=xself.y=yself.width=widthself.height=height}}

    Poichoranonesistononomidiparametriesterni, lenuoveistanzedellaclassepossonoesserecreatesolospecificandoivalorideiparametri,comemostraquestocodice:varq=Rect(2.0,2.0,5.0,5.0)

    InizializzatoridiconvenienzaGliinizializzatoridiconvenienzasonofunzionisecondariediinizializzazionechedevonoobbligatoriamente chiamare un altro inizializzatore allinterno della stessa classe e che,quindi,devonocausarelesecuzionediuninizializzatoredesignato.

    Nella sezione Definizione di una classe base, a pagina 88, abbiamo introdotto unasempliceclassechiamataProcessor,perrappresentareimicroprocessori.Lusodiquestaclasse potrebbe richiedere dei frequenti istanziamenti di una particolare classe di

  • processoree,quindi,supportarelinclusionediuninizializzatorediconvenienza:

    classProcessor{

    vardataWidth=0varaddressWidth=0varregisters=0varname=

    init(name:String,dWidth:Int,aWidth:Int,regs:Int){

    self.name=namedataWidth=dWidthaddressWidth=aWidthregisters=regs}4,5ptconvenienceinit(eightbitName:String,regs:Int)

    {self.init(name:eightbitName,dWidth:8,aWidth:16,regs:regs)}}

    Notatechelinizializzatorediconvenienzastabilisceidefaultdiduedeiquattroparametririchiestidallinizializzatoredesignato,chevieneraggiuntotramiteself.init().

    Linizializzatore di convenienza viene chiamato durante la costruzione di una nuovaistanza,comenelcodicechesegue:varp=Processor(eightbitName:6502,regs:3)

    InizializzazioneedereditarietLegerarchie tra classi introducono un nuovo livello di complessit nelmodo in cui gliinizializzatorivengonodefinitieusati,inclusoquantosegue:

    Un inizializzatore designato deve impostare i valori per tutte le proprietintrodotte nelle proprie classi, prima di chiamare linizializzatore di unasuperclasse.

    Un inizializzatore designato deve chiamare linizializzatore di una superclasseprimadiimpostareivaloridiqualunqueproprietereditata.

    Un inizializzatore di convenienza deve chiamare un altro inizializzatore nellastessa classe (di convenienza o designato) prima di impostare il valore diqualunquepropriet.

    Gliinizializzatorinonpossonochiamareleistanzedeimetodi,leggereleproprietdelleistanzeofareriferimentoaself,finoaquandotutteleproprietintrodottedalla classe e tutte quelle della gerarchia della sua superclasse siano state

  • inizializzate.

    Unaclassederivata,inSwift,normalmentenonereditagliinizializzatoridallasuperclasse,maesistonounpaiodicircostanzeincuiciaccade:

    Se la classe derivata non definisce alcun inizializzatore designato, erediterautomaticamentetuttigliinizializzatoridesignatidellasuasuperclasse.

    Se la classe derivata implementa tutti gli inizializzatori designati dellasuperclasse, conqualunquecombinazionepossibile tra ladefinizionee lereditdegli stessi, la classe erediter tutti gli inizializzatori di convenienza della suasuperclasse.

    OverridingdegliinizializzatoriPotete eseguire loverridingdelle funzioni di inizializzazione inuna classederivata,madoveteconsiderarequantosegue:

    Per sovrascrivere un inizializzatore designato, dovete far precedere la suadefinizionedallaparolachiaveoverride.

    Per sovrascrivere un inizializzatore di convenienza, occorre usare lo stessonumero di parametri, con gli stessi nomi e tipi, rispetto allinizializzatore dellasuperclassecheoggettodelloverriding,manon doveteusare laparola chiaveoverride.

    InizializzatoriobbligatoriLa parola chiave required, quando viene usata davanti a un inizializzatore, indica chequestodeveessere implementato inunaclassederivata.Eccodueargomentida tenereamente:

    Un inizializzatore designato obbligatorio deve essere ridefinito nella classederivata.

    Un inizializzatore di convenienza obbligatorio non deve essere ridefinito nellaclassederivata,severrereditatoautomaticamente,amenocheilcomportamentoereditatosiaindesiderato.

    DeinizializzazioneLadeinizializzazioneilprocedimentodipulituradituttoquelcheriguardaunistanzadi una classe, appena prima che la stessa istanza venga deallocata. Il procedimento similealdistruttoreinC++eC#,oalmetodofinalizeinJava.

    Un deinizializzatore viene dichiarato usando la parola chiave deinit, come vienemostratoquidiseguito:

    classSomeClass

  • {//altrepartidelladefinizionedellaclassedeinit{

    //codiceperpuliretuttoprimadelladeallocazione}}

    La funzione deinit viene chiamata automaticamente e non pu essere invocatadirettamente.

    Unaclassederivataeredita ildeinizializzatoredellasuasuperclasse,chevienechiamatoautomaticamentealterminedellimplementazionedeldeinizializzatorederivato.

  • Strutture

    InSwift, le strutture sono strettamente correlate alle classi (vedere la sezione Classi),chepossonorisultarenuoveperiprogrammatoriinCeObjective-C,mamoltomenopercoloro che hanno familiarit con il C++, nel quale classi e strutture sono strettamentecorrelate.

    Eccoalcuneimportantisimilitudiniedifferenze:

    Comeleclassi,lestrutturepossonoaverepropriet,istanzeetipidimetodi,sub-scripteinizializzatori,epossonosupportareestensionieprotocolli(consultatelesezioniEstensioni,apagina131,eProtocolli,apagina141).

    Le strutture non possono ereditare o essere derivate da altre strutture e nonpossonoaveredeinizializzatori.

    Le strutture sono tipi di valori,mentre le classi sono tipi di reference. Questosignificachelestrutturevengonosemprecopiatequandosonoassegnateousatecomeargomentidiunafunzione;nonvengonousatiiconteggidireference.

    Lasintassiperdichiarareunanuovastrutturahailseguenteaspetto:structStructureName

    {

    //propriet,membroedefinizionicorrelate

    }

    NOTAComeconvenzione, inomidelle strutture inizianoconuna letteramaiuscolaeusanolanotazionecamelcaseperlarimanenzadelnome.

    LeproprietnellestruttureLeproprietelerelativefunzioninellestrutturesonoinlargaparteidenticheaquelledelleclassi,quindidovresteleggerelesezioniPropriet,apagina90,eClassi,apagina87,percomprendernelebasi.

    Comeleclassi,lestrutturesupportanoleproprietmemorizzateecalcolate,gliosservatoridelleproprieteleproprietcostanti.

    Lestrutturesupportanoanche i tipi (notianchecomeclassi)dipropriet.Mentrequeste

  • vengono introdotte nelle classi per mezzo della parola chiave class, nelle strutturevengonointrodotteconlaparolachiavestatic.

    ImetodinellestruttureLestrutturepossonoaveremetodidiistanziamento,definitiusandolastessasintassiusataper leclassi.Lesempio seguentedimostrauna strutturaper rappresentare i rettangoli interminidiunpuntoangolare,unalarghezzaeunaltezza,eincludonounmetodoarea()checalcolalareadellaforma:

    structRect{

    varx=0.0,y=0.0,width=0.0,height=0.0

    funcarea()->Double{

    return(width*height)}}

    MetodimutantiDi default, i metodi ist