2015-02-23 34 views
5
jenerik tipte ise

ı Otobüs genel sınıf var diyelim:Kontrol AnyObject Swift

class Bus<T> { 
    func doSomething() {} 
} 

ve bunu örneğini oluşturabilir:

var myBus = Bus<String>() 

Şimdi bir fonksiyonu var Bu, AnyObject'un bir parametresini alır ve bu sınamaları test eder:

func checkType(object: AnyObject) { 
    if let foo = object as? String { 
     println("string") 
    } 
} 

Benim sorunum, türünün Bus türünde olup olmadığını denetlemenin bir yolu göremiyorum vetüründe doSomething() işlevini çalıştırıyor. Herhangi bir yardım takdir edilecektir.


Düzenleme: Protokoller de gerektiği bu şekilde çözmeye görünmüyor.

import Foundation 

@objc protocol BusProtocol { 
    func doSomething() -> Void 
} 

class Bus<T> : BusProtocol { 
    func doSomething() -> Void { 
     println("asdf") 
    } 
} 

func checkType(object: AnyObject) { 
    if let foo = object as? Bus<AnyObject> { 
     foo.doSomething() // no match 
    } 
    if let foo = object as? Bus<Any> { 
     foo.doSomething() // no match 
    } 
    if let foo = object as? Bus<String> { 
     foo.doSomething() // prints "asdf" 
    } 
    if let foo = object as? BusProtocol { 
     foo.doSomething() // SIGABRT -- -[SwiftObject doesNotRecognizeSelector:] 
    } 
} 

checkType(Bus<String>()) 
+1

Düzenleme örneğiniz, '@ objc' kullanarak, Swift 1.2 ile segfault görünmüyor - ancak genel sınıflardaki bu yöntemlerin bir hata (daha önce problem olan, daha az incelikle ele alınmış olması) vermez. @ objc' (çünkü Objective-C jenerikleri desteklememektedir). Ancak, protokolde '@ objc' niteleyicisini bırakırsanız, umulan gibi çalışır (yine, protokoller ve daha fazlası gibi daha fazla özellik tanıtan Swift 1.2'i kullanarak) –

cevap

0

Pratikte anladınız.

func checkType(object: AnyObject) { 
    if let foo = object as? Bus<AnyObject> { 
     print("Got here") 
    } else { 
     print("Fail") 
    } 
} 

let bus = Bus<String>() 
checkType(bus) // Fail 

let otherBus = Bus<AnyObject>() 
checkType(otherBus) // "Got Here" 

Bunun tam olarak ne istediğinizi bilmediğini biliyorum, ancak Swift'in neye ihtiyacı olduğunu gösterir.

+0

Çalışmıyor, denedim. 'T' jenerik tip için argüman alamadı ' –

+0

Ah şimdi ne soruyorsun anlıyorum. Otobüste neler olduğunu bilmek mi istiyorsunuz? Bus türünün içerdiğini önemsiyor musun? – jervine10

+1

Sadece nesnenin bir çeşit "Bus" olup olmadığını kontrol etmem ve eğer varsa doSomething() işlevini çalıştırabilmem gerek. –

6

Burada sorun, somut bir şey olarak Bus düşünmenizdir. Gerçekten değil. Bus<String> is. Bus<Int> da. Ancak Bus, en azından aynı anlamda değildir. T'un ne olduğunu bilmek gerekiyor.

Gerçekten, ne istediğini böyle bir şey yazmaktır:

func checkType<T>(object: AnyObject) { 
    if let foo = object as? Bus<T> { 
     println("Bus<T>") 
    } 
} 

Ama mümkünse kullanırsanız, bir hata alırsınız: Diğer dillerde farklı olarak

// error: Argument for generic parameter 'T' could not be inferred. 
checkType(myBus) 

, checkType<String>(myBus) yazamazsınız. Ama şu aradığınız ne olabilir:

func checkType<T>(object: AnyObject, T.Type) { 
    if let foo = object as? Bus<T> { 
     println("Bus<T>") 
    } 
} 

checkType(myBus,String.self) 

Bu T herhangi Bus<T> içindir ve düzgün çalışması ne giderir.

T'un ne olduğunu belirtmek istemediğinize itiraz edebilirsiniz. Bununla birlikte, bunun yerine, bu soruya yol açar ... bir kez object'un bir çeşit Bus olduğunu öğrendikten sonra ne yapacaksınız? Üzerinde arama yöntemleri mi planlıyorsunuz yoksa diğer işlevlere bir argüman olarak mı geçiyorsunuz? Şanslar elde etmeye çalıştığınız şey, AnyObject ve döküm kullanmak yerine genel bir işlev ve protokol kısıtlamaları ile daha iyi yapılabilir.

2

Hızlı 2'de.Eğer hatasız teşebbüs olarak x, bunu başarmak için bir protokol kullanabilirsiniz:

protocol Busish { 
    func doSomething() -> Void 
} 

class Bus<T> : Busish { 
    func doSomething() { 
    print(self) 
    } 
} 

func with_any_bus(obj:AnyObject) { 
    if let b = obj as? Busish { 
    b.doSomething() 
    } 
} 

with_any_bus(Bus<Int>()); 
with_any_bus(Bus<String>()); 

çıkışı:

swiftblah.Bus<Swift.Int> 
swiftblah.Bus<Swift.String> 

Eğer 1.2 kullanıyor görünüyor çünkü bu ya, özellikle sizin için yararlı olabilir veya olmayabilir ama belki bu soru üzerine tökezleyen birileri yararlı bulacaktır.

+0

Bu öneri için teşekkürler. Bir sınıfın genel sınıfım olup olmadığını kontrol etmek için boş bir protokol yazabildim. İşlev yok, sadece kontrol istedim. –