Qual è il rappresentante _ underscore di in Swift References?


144

Nella sezione di riferimento dei documenti di Apple ci sono molte istanze di questo genere di cose:

func runAction(_action: SKAction!)

L '"equivalente" obiettivo-C di questo è:

- (void)runAction:(SKAction *)action

Mi sembra che sia probabilmente importante che (nel riferimento Swift) ci sia uno spazio dopo il trattino basso e "azione" sia scritto in corsivo.

Ma non riesco a capire cosa stia cercando di trasmettere. Quindi forse la domanda è ... c'è un riferimento per le convenzioni utilizzate nei riferimenti?

- ecco la pagina a cui mi riferisco in questo riferimento all'uso del trattino basso: https://developer.apple.com/documentation/spritekit/sknode#//apple_ref/occ/instm/SKNode/runAction

Aggiornare

Swift 3 ha apportato alcune modifiche al modo in cui vengono utilizzati e denominati i nomi dei parametri di funzione / metodo e le etichette degli argomenti. Ciò ha conseguenze su questa domanda e sulla sua risposta. @Rickster fa un ottimo lavoro nel rispondere a una domanda diversa su _underscores in funzioni che chiariscono gran parte di questo, qui: Perché ho bisogno di sottolineatura in fretta?


3
Taggato con [underscore.js] ??
Martin R,

3
La documentazione segue la convenzione matematica dell'uso del corsivo per i nomi delle variabili. Ad esempio: sin² a + cos² a = 1.
rob mayoff,

Risposte:


116

Entrambe le risposte erano corrette ma voglio chiarire un po 'di più.

_viene utilizzato per modificare il comportamento del nome di parametro esterno per i metodi .

Nella sezione Nomi dei parametri locali ed esterni della documentazione, dice:

Swift assegna al nome del primo parametro in un metodo un nome di parametro locale per impostazione predefinita e fornisce al secondo e ai nomi dei parametri successivi sia i nomi dei parametri locali che quelli esterni per impostazione predefinita.

D'altra parte, le funzioni di default non hanno nomi di parametri esterni.

Ad esempio, abbiamo questo foo()metodo definito in classe Bar:

class Bar{
    func foo(s1: String, s2: String) -> String {
        return s1 + s2;
    }
}

Quando chiami foo(), si chiama come bar.foo("Hello", s2: "World").

Tuttavia , è possibile ignorare questo comportamento utilizzando _davanti a s2dove è dichiarato.

func foo(s1: String, _ s2: String) -> String{
    return s1 + s2;
}

Quindi, quando chiami foo, potrebbe semplicemente essere chiamato come bar.foo("Hello", "World")senza il nome del secondo parametro.

Tornando al tuo caso, runActionè un metodo perché è associato al tipo SKNode, ovviamente. Pertanto, l'inserimento di un _parametro before actionconsente di chiamare runActionsenza un nome esterno.

Aggiornamento per Swift 2.0

La funzione e il metodo ora funzionano allo stesso modo in termini di dichiarazione del nome dell'argomento locale ed esterno.

Le funzioni vengono ora chiamate utilizzando il nome del parametro esterno per impostazione predefinita, a partire dal 2o parametro. Questa regola si applica solo al codice Swift puro.

Quindi, fornendo un _davanti a una funzione , il chiamante non dovrà specificare il nome del parametro esterno, proprio come si farebbe per un metodo .


9
Confuso, se la _scrittura prima del secondo parametro, la tua risposta è abbastanza chiara; cosa succede se in func runAction(_action: SKAction!), _è prima del primo parametro o se scrivi il seguente codice func foo(_ s1: String) { // your code }Xcode ti darebbe un avvertimento, ma c'è molto codice come func bringSubviewToFront(_ view: UIView)nel riferimento, perché?
Will Zhang,

10
quindi in pratica lo fa senza motivo e confonde tutti. eccezionale.
botbot,

2
Un carattere di sottolineatura è noto come "Wildcard Pattern" developer.apple.com/library/ios/documentation/Swift/Conceptual/…
user2143356

@Wyatt Zhang, dice il documento, che l'utilizzo di _per il primo parametro è estraneo. Posso dare per scontato che i progettisti pensano che sia ovviamente abbastanza per il tuo codice e non incantano la leggibilità, al contrario, sporcano il codice. Quindi ricevi l'avvertimento. Il riferimento ha l'obiettivo opposto: deve essere il più chiaro possibile - quindi il carattere di sottolineatura del primo parametro è menzionato per OGNI metodo. Questo spiegherebbe tutto)
Dmitry Gryazin,

4
È importante notare che Swift 3.0 cambia le cose. Sono richieste tutte le etichette, se non diversamente specificato. Quindi il -prima del primo parametro non è più estraneo. Ad esempio: override func viewWillAppear(_ animated: Bool)segnala che il chiamante (codice Objective-C) non utilizzerà un'etichetta di parametro
Mr. T

85

Il carattere di sottolineatura è un token generale utilizzato per indicare un valore scartato.

In questo caso specifico, significa che la funzione verrà invocata come runAction(argument)anzichérunAction(action:argument)

In altri contesti ha altri significati simili, ad esempio in:

for _ in 0..<5 { ... }

Significa che vogliamo semplicemente eseguire il blocco 5 volte e non ci interessa l'indice all'interno del blocco.

In questo contesto:

let (result, _) = someFunctionThatReturnsATuple()

Significa che non ci interessa quale sia il secondo elemento della tupla, solo il primo.


Quindi in questo caso l'argomento (un'azione) è un'opzione?
Confuso il

1
No, causa il nome del parametro esterno (azione :) in questo caso, essere vuoto, quindi omesso. L'argomento è ancora richiesto, non è semplicemente taggato con azione :.
David Berry,

4
La vera risposta è una combinazione della risposta di @ dasblinkenlight e della mia. Affronta questo caso specifico in modo più preciso, mentre il mio affronta la domanda più ampia, cosa significa _?
David Berry,

4
Puoi usare il segno di eliminazione anche per numeri molto grandi per renderli più leggibili in questo modolet pi = 3.141_592_653_59
SMP

in modo divertente, puoi anche usarlo per rendere meno leggibili numeri molto grandi, comelet pi = 3.1_4_15_92___63
David Berry,

15

Da Swift 3 tutte le etichette degli argomenti sono richieste per impostazione predefinita .

È possibile forzare un IDE con cui nascondere un'etichetta argomento _.

func foo(a: String) {
}

func foo2(_ a: String) {
}

chiamato foo(a: "abc")efoo2("abc")

Nota: questo può essere usato solo quando si atrovano contemporaneamente l' etichetta dell'argomento (esterno) e il nome della variabile (interna) . È equivalente - func foo(a a: String)non accetta il _.

Perché lo sta usando Apple?

Puoi vedere che Apple lo sta usando attraverso l'API. Le librerie di Apple sono ancora scritte in Objective-C (in caso contrario, condividono comunque gli stessi nomi di funzioni, che sono state progettate per la sintassi Objective-C)

Funzioni come applicationWillResignActive(_ application: UIApplication)avrebbero un nome di parametro ridondanteapplication , poiché esiste già l' applicazione nel suo nome di funzione.

Il tuo esempio

func runAction(_ action: SKAction!)sarebbe chiamato senza il suo _segno come runAction(action:). Il nome del parametro actionsarebbe ridondante poiché ce n'è già uno nel nome della funzione. Questo è lo scopo e perché è lì.


13

Un identificatore davanti alla dichiarazione di parametro definisce un nome di parametro esterno . Questo è il nome che deve essere fornito dal chiamante quando chiama la funzione:

func someFunction(externalParameterName localParameterName: Int)

Swift fornisce un nome esterno automatico per qualsiasi parametro predefinito definito, se non si fornisce un nome esterno da soli. L'utilizzo di un carattere di sottolineatura per il nome del parametro esterno esclude questo comportamento:

È possibile annullare questo comportamento scrivendo un carattere di sottolineatura ( _) anziché un nome esterno esplicito quando si definisce il parametro.

Puoi leggere ulteriori informazioni su questo comportamento nella sezione Nomi esterni per parametri con valori predefiniti qui .


quindi ... fammi vedere se la mia debolezza ha capito bene. In questo esempio dovrei nominare la variabile / costante del mio parametro come "azione" e assegnarlo all'azione SKA che voglio eseguire da questa funzione, e Swift nomina automaticamente il parametro predefinito richiesto "azione". TUTTAVIA, se voglio assegnare un nome personalizzato a questa azione, devo usare il carattere di sottolineatura nella chiamata della funzione?
Confuso il

4
@Confused La mia comprensione è che SKi designer non vogliono che tu scriva actiondue volte, perché "action" fa già parte del nome della funzione. In altre parole, non vogliono che tu scriva sprite.runAction(action:moveGroundSpritesForever). Lo scopo dei nomi di parametri esterni era di far "leggere come una frase" il codice; l'uso di actiondue volte ne vanificherebbe lo scopo.
dasblinkenlight,

Alcune luci si accesero nell'oscurità. Penso di averlo capito. Questa funzione del linguaggio ha lo scopo di rendere le funzioni di chiamata in Swift molto simili a come si chiamerebbe un metodo con parametri in Objective-C. Può essere.
Confuso il

1
Tuttavia, il carattere di sottolineatura può essere usato in qualche modo per rifiutare di avere questi nomi di parametri esterni per i parametri definiti con un valore predefinito ... ma non ho ancora visto come è stato fatto. Continuerà a cercare.
Confuso il

Quindi ... in breve, passa semplicemente tra parametri nominati e parametri ordinali, quindi puoi facilmente alternare tra foo.bar(param: 'fiddle') e foo.bar('fiddle') NOTA: con un solo argomento non diventa davvero evidente ... ma con più argomenti diventa molto rilevante: foo.bar(param1: 'fiddle', param2: 'dee') vs foo.bar('fiddle','dee')
jrypkahauer,

10

Penso che questo costringa una convenzione in Swift che la renda più vicina all'obiettivo-c, che corrisponda meglio alle convenzioni sul cacao. In objc non si nomina (esternamente) il primo parametro. Invece, per convenzione di solito includi il nome esterno nell'ultima parte del nome del metodo in questo modo:

- (void)myFancyMethodWithFirstName:(NSString *)aFirstName lastName:(NSString *)aLastName;

[someInstance myFancyMethodWithFirstName:@"John" lastName:@"Doe"];

Per rendere le chiamate API Swift coerenti con objc, è necessario sopprimere il nome del parametro esterno del primo parametro.

func myFancyMethodWithFirstName(_ firstName:String, lastName:String);

someInstance.myFancyMethodWithFirstName("John", lastName:"Doe")

2
Mi piace questa spiegazione. avendo imparato prima Obj-C, hai chiarito le cose. Sottolinea inoltre l'importanza di nominare il metodo in modo appropriato in Swift, vale a dire che l'ultima parte del nome del metodo dovrebbe descrivere il primo argomento, come è generalmente il caso in Obj-C. roba buona.
rrrrrraul,

5

In realtà, c'è una differenza tra il codice reale utilizzato per definire un metodo e la dichiarazione del metodo nei documenti di Apple. Prendiamo UIControl s' - addTarget: azione: forControlEvents: metodo per esempio, il codice reale è: inserisci qui la descrizione dell'immagine

Ma nei documenti, appare così (nota _ prima del target): inserisci qui la descrizione dell'immagine

Nel codice reale, _ viene utilizzato per non visualizzare il nome esterno del secondo o successivo parametro quando viene chiamato un metodo, mentre nei documenti, _ prima che il nome locale di un parametro indichi che quando si chiama un metodo o una funzione, non è necessario fornire un nome esterno.

Non esiste un nome esterno quando una funzione viene chiamata per impostazione predefinita a meno che tu non fornisca il tuo o aggiunga # prima (senza spazi bianchi) il nome locale di un parametro, ad esempio, è così che utilizziamo dispatch_after : inserisci qui la descrizione dell'immagine

E nei documenti, appare così (nota tre _): inserisci qui la descrizione dell'immagine

La convenzione della dichiarazione della funzione è la stessa che ho descritto per il metodo.


1

Solo più visivamente.

inserisci qui la descrizione dell'immagine

Come puoi vedere _basta omettere o meno un nome di parametro locale.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.