假设我有一个课程class C<T>
。
我想编写一个函数f(_ a: Any) -> Bool
,当a
是从C
继承的类的成员(或者是C
本身)时,该函数返回true。我不在乎专业化:传递C<Int>
,C<Double>
,C<Whatever>
应该都返回true
。
看来我应该能够将a is C
或a as? C != nil
编写为该函数的主体,但是,它们都不能在操场上编译。 swiftc抱怨说“无法将通用参数'T'强制转换为'C '”。如果我将f
作为实例方法写在C
内部,则C
是隐式C<T>
,因此编写let c = C<Int>(); c.f(C<Double>())
会返回false
。
我可以通过编写一个符合P
的协议C
并进行测试来解决此问题,但我认为这不是一个好的解决方案。这只是一个hack。
有什么办法吗?
这是我为尝试此操作而编写的所有代码:
class C<T> {
func test(_ a: Any) -> (Bool, Bool) {
return (type(of: a) == C.self, a is C)
}
}
class D: C<Double> { }
let d = D()
func f(_ a: Any) -> Bool {
return a is C // generic parameter 'T' could not be inferred in cast to 'C<_>'
}
d.test(C<Int>()) // false, false
// bad solution
protocol P { }
extension C: P { }
d is P // true
最佳答案
我认为没有语言功能可让您执行此操作,因为仅知道对象是其自身的子类或C
本身的子类,而不知道通用类型参数并没有用。
我的意思是,您知道someObj
确实是C<Something>
类型,但是知道Something
是什么之后,该怎么办? someObject
您无能为力。您无法投射它,因此无法访问它的任何成员。
Swift的泛型非常严格,与Java不同,Java只是在运行时将泛型类型抛出窗口外...
如果您坚持要执行此操作,则唯一的选择就是使用您提到的hack。
或者,如果您只想检查a
是否为C
本身,而不是其任何子类,则可以使用此代码(只是为了好玩):
func f(a: Any) -> Bool {
let regex = try! NSRegularExpression(pattern: "C<.+>")
let typeString = String(describing: type(of: a))
let range = NSRange(location: 0, length: typeString.characters.count)
let matchRange = regex.rangeOfFirstMatch(in: typeString, range: range)
return range.toRange() == matchRange.toRange()
}
关于swift - 如何测试对象是继承还是泛型类的成员?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/44350689/