假设我有一个课程class C<T>

我想编写一个函数f(_ a: Any) -> Bool,当a是从C继承的类的成员(或者是C本身)时,该函数返回true。我不在乎专业化:传递C<Int>C<Double>C<Whatever>应该都返回true

看来我应该能够将a is Ca 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/

10-15 08:08