假设我有一个通用类总线:
class Bus<T> {
func doSomething() {}
}
我可以创建它的实例:
var myBus = Bus<String>()
现在我有一个函数,它获取AnyObject
的一个参数并测试它的类型:
func checkType(object: AnyObject) {
if let foo = object as? String {
println("string")
}
}
我的问题是,我看不到一种方法来检查object
是否属于Bus
类型,如果它属于Bus
类型,则运行函数doSomething()
。如有任何帮助,我们将不胜感激。
编辑:协议似乎也没有以应有的方式解决这个问题。
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>())
这里的问题是您将Bus
视为一个具体的东西。事实并非如此。Bus<String>
是。Bus<Int>
也是。但Bus
不是,至少在同一意义上不是。你需要知道什么是T
。
真的,你想要的是写这样的东西:
func checkType<T>(object: AnyObject) {
if let foo = object as? Bus<T> {
println("Bus<T>")
}
}
但如果你尝试使用它,你会得到一个错误:
// error: Argument for generic parameter 'T' could not be inferred.
checkType(myBus)
与其他语言不同,您不能编写checkType<String>(myBus)
。但以下可能会满足您的需求:
func checkType<T>(object: AnyObject, T.Type) {
if let foo = object as? Bus<T> {
println("Bus<T>")
}
}
checkType(myBus,String.self)
这修复了任何Bus<T>
的T
,并将正常工作。
你可能会反对你不想指定T
是什么。然而,这却引出了一个问题。。。一旦你发现object
是某种Bus
,你会怎么做?您是打算调用它的方法,还是将它作为参数传递给其他函数?与使用AnyObject
和强制转换相比,使用通用函数和协议约束可以更好地实现您想要实现的目标。
在swift 2.x中,您可以使用一个协议来实现这一点,正如您尝试的那样,没有错误:
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>());
输出:
swiftblah.Bus<Swift.Int>
swiftblah.Bus<Swift.String>
这可能对你特别有帮助,也可能没有帮助,因为你似乎在使用1.2,但也许其他人会发现这个问题很有用。
你实际上已经得到了。
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"
我知道这不是你真正想要的,但它表明了斯威夫特的需求。