2015-05-05 4 views
5

cercando di giocare con le estensioni, ma sto avendo problemi di ottenere quanto segue per lavorare:Perché questa estensione di base non funziona?

let value = -13 
abs(value) 

extension Int { 
    var abs:Int { 
     return abs(self) // -> Cannot invoke 'abs' with an argument list of type '(Int)' 
    } 
} 

value.abs 

L'errore di compilazione è strano, perché corre dimostrabile la funzione abs() direttamente sopra con una Int come argomento. Ho ancora alcune lampadine da innescare per i generici, immagino. Illuminami.

+0

Aha! Grazie a entrambi. Lo capisco adesso. La prima persona a modificare la sua risposta per mostrare che posso impostare la funzione libera come 'Swift.abs (self)' ottiene il 'accept': D –

+0

Inoltre, questo è il motivo per cui odio il sé implicito. –

risposta

4

Il compilatore Swift è confuso che si usi la variabile abs come una funzione, che non può fare. Ora puoi guardare tutte le risposte e rinominare la tua variabile, ma queste non danno un'idea di come funzionano le funzioni di Swift.

Swift importa automaticamente il framework Swift, dove definisce le sue funzioni statiche. Per utilizzare queste funzioni, in genere non è necessario specificare che sia dal framework, ma in casi come questo, è necessario specificare che si desidera utilizzare il metodo abs dal framework Swift.

Così, dopo tutto la spiegazione, ecco il codice, che funziona:

let value = -13 
abs(value) 

extension Int { 
    var abs: Int { 
     return Swift.abs(self) 
    } 
} 

value.abs 
2

Appare solo un problema di risoluzione delle chiamate. Ciò funzionerà:

let value = -13 
abs(value) 


extension Int { 
    var abs1:Int { 
     return abs(self) 
    } 
} 

value.abs1 

E questo funzionerà anche:

extension Int { 
    var abs:Int { 
     return self < 0 ? -self : self 
    } 
} 

value.abs 
2

Il problema qui è che si sta estendendo Int di aggiungere una variabile denominata abs - che è anche il nome della funzione che si stanno chiamando.

Quando si tenta di chiamare la funzione abs() sul Int, vede la variabile abs che è stato creato ed è confuso perché pensa che si sta tentando di restituire quella variabile e non capisce il motivo per cui si sta inviando un parametro .

Se si rinomina la variabile su absoluteValue o altro, dovrebbe funzionare.

let value = -13 
abs(value) 

extension Int { 
var absoluteValue:Int { 
     return abs(self) 
    } 
} 

value.abs 

Aggiornamento: Come altri hanno detto, si può anche risolvere il disambiguazione dell'uso di abs richiamando esplicitamente la funzione nel quadro Swift. Questo dovrebbe funzionare altrettanto bene della soluzione di cui sopra.

let value = -13 
abs(value) 

extension Int { 
var abs:Int { 
     return Swift.abs(self) 
    } 
} 

value.abs 

Anche se, personalmente, vorrei ancora rinominare la mia nuova funzione per absoluteValue come nel primo esempio, in modo che il suo chiaro che non sta chiamando il Swift.abs() quando si utilizza la variabile abs.

0

Grazie alla direzione delle due risposte originali (lo scontro tra la funzione globale libera e la variabile che stavo definendo), devono essere disambiguati. Piuttosto che implementare in modo addizionale gli addominali o essere costretto a usare un nome diverso, posso spaziare correttamente all'interno dello abs() usando lo spazio dei nomi Swift.

extension Int { 
    var absoluteValue:Int { 
     return Swift.abs(self) 
    } 
} 

Questo mi dà il meglio di entrambi i mondi (IMO).