检查AnyObject在Swift中是否为泛型类型



假设我有一个通用类总线

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"

我知道这不是你真正想要的,但它表明了斯威夫特的需求。

最新更新