Posso creare un'estensione array che si applica, ad esempio, solo stringhe?È possibile creare un'estensione di array in Swift che è limitato a una classe?
risposta
Al Swift 2, questo può ora essere realizzato con protocollo estensioni, che forniscono metodo e proprietà implementazioni tipi conformi (opzionalmente limitati da vincoli aggiuntivi).
Un semplice esempio: Definire un metodo per tutti i tipi conformi a SequenceType
(come Array
) quando l'elemento sequenza è una String
:
extension SequenceType where Generator.Element == String {
func joined() -> String {
return "".join(self)
}
}
let a = ["foo", "bar"].joined()
print(a) // foobar
Il metodo di estensione non può essere definito per struct Array
direttamente, ma solo per tutti i tipi conforme ad alcuni protocolli (con vincoli opzionali). Quindi uno deve trovare un protocollo a cui è conforme Array
e che fornisce tutti i metodi necessari. Nell'esempio sopra, questo è SequenceType
.
altro esempio (una variazione di How do I insert an element at the correct position into a sorted array in Swift?):
extension CollectionType where Generator.Element : Comparable, Index : RandomAccessIndexType {
typealias T = Generator.Element
func insertionIndexOf(elem: T) -> Index {
var lo = self.startIndex
var hi = self.endIndex
while lo != hi {
// mid = lo + (hi - 1 - lo)/2
let mid = lo.advancedBy(lo.distanceTo(hi.predecessor())/2)
if self[mid] < elem {
lo = mid + 1
} else if elem < self[mid] {
hi = mid
} else {
return mid // found at position `mid`
}
}
return lo // not found, would be inserted at position `lo`
}
}
let ar = [1, 3, 5, 7]
let pos = ar.insertionIndexOf(6)
print(pos) // 3
Qui il metodo è definito come un'estensione CollectionType
perché necessita accesso pedice agli elementi, e gli elementi vengono richiesto di essere Comparable
.
Puoi cambiare 'Indice == Int' a' Indice: RandomAccessIndexType' con alcune modifiche minori, ad es. 'startIndex' invece di' 0', 'endIndex.predecessor()', 'let mid = lo.advancedBy (lo.distanceTo (hi)/2)' più un bail anticipato su 'isEmpty'. Significherebbe, ad esempio, che funzionerebbe con 'String.UTF16View', che è ad accesso casuale ma non intero indicizzato. –
@AirspeedVelocity: Fatto :) –
AGGIORNAMENTO: Vedere la risposta di Martin sotto per gli aggiornamenti di Swift 2.0. (Non posso cancellare questa risposta in quanto è accettata, se Doug può accettare la risposta di Martin, io elimino questo per evitare confusioni.)
Questo ha messo più volte nei forum, e la risposta è no, non puoi farlo oggi, ma capiscono che è un problema e sperano di migliorarlo in futuro. Ci sono cose che vorrebbero aggiungere a stdlib che ha anche bisogno di questo. Ecco perché ci sono così tante funzioni gratuite è stdlib. La maggior parte di questi sono work-around per questo problema o il problema di "nessuna implementazione predefinita" (ad esempio "tratti" o "mixin").
Grazie, sembra una strana omissione. Terrò le dita incrociate. –
Potrebbe voler modificare questo per 2.0, esp. come se vi si riferissero i dupes. –
Non hai ancora fornito un caso d'uso, nonostante molte richieste nei commenti, quindi è difficile sapere cosa stai cercando. Ma, come ho già detto in un commento (e Rob ha detto in una risposta), non lo capirai letteralmente; le estensioni non funzionano in questo modo (al momento).
Come ho detto in un commento, quello che vorrei fare è racchiudere l'array in una struttura. Ora la struct custodisce e garantisce il tipo di stringa, e abbiamo l'incapsulamento. Ecco un esempio, anche se naturalmente è necessario tenere a mente che hai dato alcuna indicazione del tipo di cosa vuoi veramente fare, quindi questo potrebbe non essere direttamente soddisfacente:
struct StringArrayWrapper : Printable {
private var arr : [String]
var description : String { return self.arr.description }
init(_ arr:[String]) {
self.arr = arr
}
mutating func upcase() {
self.arr = self.arr.map {$0.uppercaseString}
}
}
Ed ecco come chiamarla:
let pepboys = ["Manny", "Moe", "Jack"]
var saw = StringArrayWrapper(pepboys)
saw.upcase()
println(saw)
Così abbiamo isolato efficacemente la nostra matrice di stringhe in un mondo in cui possiamo armare con funzioni che si applicano solo a matrici di stringhe. Se pepboys
non fosse un array di stringhe, non avremmo potuto avviarlo in un StringArrayWrapper per cominciare.
Se la matrice è probabile che sia grande, una classe potrebbe essere migliore di una struttura, in modo da garantire il pass-by-reference. Spesso avvolgo i grandi array nelle classi proprio per questo motivo, in modo che il loro passaggio non comporti alcuna copia. – matt
Swift utilizza il copy-on-write per il pass-by-value, quindi nella maggior parte dei casi non dovrebbe esserci un costo maggiore nel passare grandi array. Se trovi un costo maggiore, dovresti aprire un radar. Apple ha notato in particolare che non si dovrebbe cercare di evitare la copia per motivi di prestazioni. Vedere la nota in fondo a https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/ClassesAndStructures.html –
@RobNapier La proprietà qui è un 'var' e l'esempio presuppone che sarà essere scritto a – matt
Questo è già stato risposto dai tre saggi sopra ;-), ma umilmente offro una generalizzazione della risposta di @ Martin. Possiamo scegliere come target una classe arbitraria usando il protocollo "marker" che viene implementato solo sulla classe che vogliamo targetizzare. Vale a dire. non è necessario trovare un protocollo per-se, ma può creare un banale per l'utilizzo nel targeting della classe desiderata.
protocol TargetType {}
extension Array:TargetType {}
struct Foo {
var name:String
}
extension CollectionType where Self:TargetType, Generator.Element == Foo {
func byName() -> [Foo] { return sort { l, r in l.name < r.name } }
}
let foos:[Foo] = ["c", "b", "a"].map { s in Foo(name: s) }
print(foos.byName())
- 1. è possibile creare una chiusura generica in Swift?
- 2. È possibile convertire una classe Swift in C void * pointer?
- 3. Non è possibile creare un array di LinkedList in Java ...?
- 4. È possibile utilizzare std :: array in una classe constexpr?
- 5. Come creare un array di classe a Swift
- 6. È possibile creare un oggetto senza una classe in C#?
- 7. È possibile rilevare una NSInternalInconsistencyException in Swift?
- 8. Swift Proprietà che è conforme a un protocollo e Classe
- 9. È possibile eseguire meta-programmazione in Swift
- 10. È possibile creare un array multidimensionale vuoto in javascript/jquery?
- 11. In PHP, è possibile creare un'istanza di una classe senza chiamare il costruttore della classe?
- 12. Come sottoclasse una classe di array in Swift?
- 13. È possibile creare un riferimento a un metodo di classe astratta in un metodo di classe che non lo estende?
- 14. Generics Java: Non è possibile creare una matrice di una classe annidata
- 15. È possibile aggiungere una funzione a un array JavaScript dirottato?
- 16. In Oracle è possibile creare una tabella che esiste solo mentre il database è in esecuzione?
- 17. È possibile restituire un array di stringhe
- 18. È possibile dichiarare una relazione dopo che la classe è stata creata da automap in SqlAlchemy
- 19. È possibile convertire un array di stringhe in una stringa?
- 20. È possibile istanziare una classe astratta?
- 21. È possibile creare una tela trasparente
- 22. È possibile a chiunque creare una certificazione falsa?
- 23. Perché non è possibile creare un'istanza di una matrice vuota di una classe nidificata?
- 24. jQuery - rimuovere una classe che è in una matrice
- 25. Array associativo in Delphi, array con chiave stringa è possibile?
- 26. È possibile aggiungere una classe a un pulsante tinyMCE personalizzato?
- 27. È possibile eseguire Swift REPL in una sessione SSH?
- 28. è possibile assegnare una funzione a una variabile di classe in fase di runtime in php?
- 29. È possibile passare dati a EventArgs senza creare una classe derivata?
- 30. È possibile creare una shell C interattiva?
Non sai cosa intendi, puoi dire di più sul tuo intento? Forse un esempio? – dpassage
@dpassage È possibile estendere le cose con il requisito che le classi estese aderiscano a un protocollo (https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Extensions.html), sono curioso se è possibile restringerlo ulteriormente solo a una classe, in modo che la mia estensione in Swift si applichi solo agli array di stringhe. –
Ma descrivi ciò che vuoi come estensione a _do_. È solo una questione di una funzione? Quindi definire una funzione generica globale. Dare un caso d'uso effettivo per ciò che si spera di ottenere. – matt