2014-12-29 25 views
16

Sono nuovo di Swift e ho utilizzato alcuni tutorial e molti di loro definiscono una funzione più di una volta con lo stesso nome.Funzioni multiple con lo stesso nome

Sono abituato ad altri linguaggi di programmazione in cui questo non può essere eseguito altrimenti genera un errore.

Quindi ho controllato il funzionario Swift Manual e anche controllato la parola chiave override per vedere quello che ho potuto uscire di esso, ma ancora non riesco a capire il seguente codice:

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 
    return 10 
} 

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { 
    let cell: UITableViewCell = UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "MyTestCell") 

    cell.textLabel?.text = "Row #\(indexPath.row)" 
    cell.detailTextLabel?.text = "Subtitle #\(indexPath.row)" 

    return cell 
} 

Da quello che posso vedere la function tableView è impostato nella riga n. 1 e nella riga n. 5, l'unica differenza che ho notato è che la prima funzione tableview restituisce Int e la seconda restituisce Object (UITableViewCell).

In questo caso vedo dal risultato che la seconda funzione NON sostituisce la prima.

Che cosa significa e perché è possibile definire una funzione più volte con lo stesso nome senza sovrascriverla?

risposta

20

Hai il permesso di definire due funzioni con lo stesso nome se hanno tipi differenti, o se essi si distingue per il loro parametro esterno etichette di argomento. Il tipo di una funzione è composto dal parametro Types tra parentesi, seguito da ->, seguito dal tipo restituito. Si noti che le etichette degli argomenti NON fanno parte del Tipo della funzione. (ma vedi AGGIORNAMENTO di seguito.)

Ad esempio, le seguenti funzioni entrambi hanno lo stesso nome e sono di tipo (Int, Int) -> Int:

// This: 
func add(a: Int, b: Int) -> Int { 
    return a + b 
} 

// Is the same Type as this: 
func add(x: Int, y: Int) -> Int { 
    return x + y 
} 

Questo produrrà un errore di compilazione - la modifica delle etichette a:b:-x:y: non distingue il due funzioni. (Ma vedere Update sotto.)

Utilizzando le funzioni del signor Web come esempi:

// Function A: This function has the Type (UITableView, Int) -> Int 
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { ... } 

// Function B: This function has the Type (UITableView, NSIndexPath) -> UITableViewCell 
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { ... } 

// Function C: This made up function will produce a compile-time error because 
// it has the same name and Type as Function A, (UITableView, Int) -> Int: 
func tableView(arg1: UITableView, arg2: Int) -> Int { ... } 

Funzione A e la funzione B di cui sopra non sono in conflitto, perché sono di diversi tipi. Funzione A e Funzione C sopra do conflitto perché hanno lo stesso Tipo. La modifica delle etichette dei parametri non risolve il conflitto se i tipi rimangono gli stessi.(vedere Update di seguito.)

override è un concetto del tutto diverso, e credo che alcune delle altre risposte coprire, quindi salterò esso.

AGGIORNAMENTO: parte di ciò che ho scritto sopra non è corretto. È vero che le etichette dei parametri di una funzione non fanno parte della definizione di Tipo, ma possono essere usate per distinguere due funzioni che hanno lo stesso Tipo, purché la funzione abbia etichette esterne diverse in modo che il compilatore possa dire quale funzione che stai cercando di chiamare quando la invochi. Esempio:

func add(a: Int, to b: Int) -> Int { // called with add(1, to: 3) 
    println("This is in the first function defintion.") 
    return a + b 
} 

func add(a: Int, and b: Int) -> Int { // called with add(1, and: 3) 
    println("This is in the second function definition") 
    return a + b 
} 

let answer1 = add(1, to: 3) // prints "This is in the first function definition" 
let answer2 = add(1, and: 3) // prints "This is in the second function definition" 

Quindi, l'uso di etichette esterni in una definizione di funzione consente funzioni con lo stesso nome e dello stesso tipo per compilare. Pertanto, sembra che sia possibile scrivere più funzioni con lo stesso nome, purché il compilatore possa distinguerle in base al loro tipo o alle loro etichette di firma esterna. Non penso che le etichette interne siano importanti. (Ma spero che qualcuno mi corregga se sbaglio.)

+0

+1 per includere la spiegazione dell'etichetta esterna. L'ho trovato nella libreria di simd e, anche se fico, sono rimasto sorpreso che fosse permesso così è andato a cercare e ho trovato la tua risposta. 'public init (_ columns: [double3])' e 'public init (rows: [double3])' sono entrambi inizializzatori validi per 'double3x3' ed entrambi hanno lo stesso tipo di firma. – Omegaman

+0

Più precisamente: si desidera utilizzare i nomi dei parametri (per la definizione interna) e le etichette degli argomenti (per le chiamate esterne). Non le etichette dei parametri. (Si prega di correggermi se ho torto o non è così preciso penso di essere) – SLN

+0

Sembra che ci siano più avvertimenti a questo. Vale a dire, se una classe rapida estende una classe Obj-C, o se avete annotato entrambe le funzioni con @objc, non sarete in grado di sovraccaricare in base al tipo, poiché i selettori sono gli stessi. Correlato, è possibile escludere un metodo dall'essere un selettore objc quando si estende una classe objc, cioè l'annotazione opposta a @objc? –

0

Le funzioni non sono le stesse sono diverse. Perché non prendono gli stessi argomenti e restituiscono cose diverse. Questa è la spiegazione semplice se non capisci i farmaci generici.

5

Stai pensando a sovraccarico di funzione.

Un estratto dalla documentazione di Apple here:

È possibile sovraccaricare una funzione generica o di inizializzazione, fornendo diversi vincoli, requisiti, o entrambi sui parametri di tipo nel la clausola parametro generico. Quando si chiama una funzione generica o un inizializzatore sovraccaricata, il compilatore utilizza questi vincoli per risolvere quale funzione sovraccaricata o inizializzatore da richiamare.

Ad esempio:

protocol A { } 
protocol B { } 

class A1: A { } 
class A2: A { } 

class B1: B { } 
class B2: B { } 

func process<T: A>(value: T) 
{ 
    // process values conforming to protocol A 
} 

func process<T: B>(value: T) 
{ 
    // process values conforming to protocol B 
} 

o:

func process(value: Int) 
{ 
    // process integer value 
} 

func process(value: Float) 
{ 
    // process float value 
} 

Questo è solo tipica confusione che potrebbe verificarsi durante un Objective-C a Swift transizione. Dovresti leggere i nomi dei parametri here.

+0

Grazie, ho visto la documentazione che hai pubblicato e anche guardato il 'The Swift Programming Language Book' di Apple. Ci sono pochissimi dati al riguardo, potresti spiegarlo meglio? –

+0

Grazie, non ho ancora appreso del materiale ' (...)'. Potresti usare un tipo di funzione classico? (Come: 'func process (a: Int) -> Int') –

+0

Le funzioni nella domanda non hanno nulla a che fare con sovraccarico o generici. – jrturton

2

In Swift, come in Objective-C, i parametri di una funzione fanno parte della definizione. Non ci sono due funzioni chiamate tableView, c'è una funzione chiamata tableView(tableView:, numberOfRowsInSection:) e uno chiamato tableView(tableView:, cellForRowAtIndexPath:)

+0

Quindi l'errore sarebbe se io dichiari 2 funzioni con lo stesso nome, valore di ritorno e parametri, come 'func one (i: Int) -> Int' e' func one (i: Int) -> Int', sono I destra? –

+2

Questo sarebbe un errore in fase di compilazione e il progetto non verrà generato. – jrturton

Problemi correlati