2014-06-12 13 views
39

ich eine Erweiterung einer Klasse machen will das Laufzeittyp-Objekt zurückgebenWie kann ich wieder instanceType in Swift

zum Beispiel erstelle ich extenstion die Klasse A

extension A { 
    class func niceObject() -> XXXXX { // in objective-c is instancetype 
     return .... 
    } 
} 

jemand also wissen, dass es instanceType Stichwort in Swift oder nicht xxxxx ersetzen und ich kann werfen diese Funktion auf Unterklasse von A aufrufen, ohne manuell

var b: B = B.niceObject() 

Dank

+0

Werfen Sie einen Blick auf diese Seite der Swift-Programmiersprachen-Ressourcen, insbesondere "Downcasting": https://developer.apple.com/library/prerelease/ios/documentation/swift/conceptual/swift_programming_language/TypeCasting.html#//apple_ref/doc/uid/TP40014097-CH22-XID_446 –

Antwort

39

Sie es tun können. Spielplatzcode unten. Es ist self(), das niceObject() zurückgeben muss. Darüber hinaus müssen Sie eine required Init auf der Basisklasse haben.

+2

In meinem persönlichen Fall, ich habe das gleiche mit 'Verlängerung A tun { Klasse func niceObject() -> [Self] { // stopft sie Rückkehr MyArrayOfSelf } }'
Es funktioniert nicht, Leider unterstützt –

+0

nicht dynamicType diese https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Types.html. Wenn Sie also nur Basisklassenreferenzen haben, funktioniert es –

10

Zumindest in Procotolen können Sie Self verwenden. Dies stellt den tatsächlichen Typ von self dar. Nicht sicher Erweiterungen, obwohl ...

Zum Beispiel finden Sie in der Definition von Equatable:

protocol Equatable { 
    func ==(lhs: Self, rhs: Self) -> Bool 
} 
+0

Beachten Sie, dass, wenn Sie zum Beispiel eine 'Erweiterung' für ein' Dictionary' machen und den gleichen Typ von 'Dictionary' zurückgeben möchten , müssten Sie' Extension Dictionary machen { \t func changeSomeThing() -> Wörterbuch { \t \t Rückkehr Selbst \t} } ' – brahimm

17

Es ist ein Schlüsselwort Self, die an zwei Stellen erlaubt - in Protokollen (siehe Jean-Philippe Pellet Antwort) und als Ergebnis der class Methoden:

extension A { 
    class func niceObject() -> Self? { 
     return nil 
    } 
} 

Leider ist dies wird nicht helfen, da die folgende ungültig ist

extension A { 
    class func niceObject() -> Self? { 
     //A can't be converted to Self 
     return A() 
    } 
} 

Der Fehler verursacht durch die Tatsache, dass, wenn Sie von A

class B : A { 
} 

erben dann

var b = B.niceObject() 

würde eine A Instanz tatsächlich zurück, die nicht konvertierbar Self ist (Self ist B)

@Grimxn hat die richtige Lösung gefunden (See his answer):

Sie müssen der Basisklasse einen erforderlichen Initialisierer hinzufügen, z.

class A { 
    @required init() { 
    } 
} 

und dann können Sie die initialiser rufen mit self()

extension A { 
    class func niceObject() -> Self { 
     return self() 
    } 
} 
+0

ich denke, der Fehler, den Sie erwähnen, ist nicht wegen der Lauf' '' B.niceObject() '' '. Es ist Kompilierfehler. Es scheint so, als könnten wir Self in Erweiterung nicht verwenden, außer wir können den Objekttyp Self zurückgeben. –

+1

@ZoonNooz Ich habe versucht zu erklären, warum wir in Swift kein 'Self' zurückgeben können. Es würde jedoch helfen, wenn wir auf 'Selbst' als Typ in dieser Methode zugreifen könnten. – Sulthan

+0

Ich habe verstanden, was du jetzt meinst. BTW in meiner Situation in objc, frage ich NSManagedObject in Coredata-Basis auf dem aktuellen Typ. also kann ich es als NSManagedObject zurückgeben und es wird Unterklasse Typ sein, wenn ich Funktion aufrufen. Aber nicht in schnell. –

0

Wenn Sie eine Swift API von Objective-C verwenden, führt der Compiler normalerweise eine direkte Übersetzung durch. Zum Beispiel wird die Swift-API func playSong(name: String) in Objective-C als - (void)playSong:(NSString *)name importiert.

Es gibt jedoch eine Ausnahme: Wenn Sie eine Swift initializer in Objective-C verwenden, fügt der Compiler den Text "initWith" an den Anfang der Methode und ordnungsgemäß das erste Zeichen im ursprünglichen Initialisierer groß geschrieben.

Zum Beispiel wird dieser Swift-Initialisierer init (songName: String, artist: String) in Objective-C als - (instancetype)initWithSongName:(NSString *)songName artist:(NSString *)artist importiert.

Verwandte Themen