检查泛型类的类型,而不考虑泛型类型约束

时间:2016-01-02 16:11:10

标签: swift generics

我有以下结构:

班级A

class A<T: SomeInterface> : C {

}

班级B

class B : SomeInterface {
    func someFunc(param: C){
        // check if param is of class A with `self.dynamicType` generic type
        if let typedC = param as? A<self.dynamicType> { // does not work

        }
    }
}

我想检查param是否有B类作为通用约束。有没有办法指定通配符泛型类型?事实上,通用约束是否属于B类型并不重要,但这也不可能:

class B : SomeInterface {
    func someFunc(param: C){
        // check if param is of type A 
        if let typedC = param as? A { // don't check generic constraint type

        }
    }
}

或(如果有通配符):

class B : SomeInterface {
    func someFunc(param: C){
        // check if param is of type A with wildcard (Is there such a thing as a wildcard?)
        if let typedC = param as? A<?> { // don't require specific generic type, just enter if param is of type A

        }
    }
}

编辑 - 游乐场样本

import UIKit

protocol SomeInterface{
  func someFunc(param: C)
}

class C {


}

class A<T: SomeInterface> : C{

}

class B : SomeInterface {

  func someFunc(param: C) {

    // A is a subclass of C, but I want the typed generic subclass
    if let typed = param as? A<self.dynamicType> {

    }

  }

}

let b = B()
let a = A<B>()
b.someFunc(a)

2 个答案:

答案 0 :(得分:1)

定义时:

path

你没有定义一个类,所以是一个类型,但是一个泛型类型A,必须被实例化为某种类型。

所以,你不能用这种方式在另一个类中定义一个函数:

path

这将始终提供类型错误。相反,你应该定义:

class A<T: SomeInterface>{

}

例如,由于您已将func someFunc(paramA: A) 定义为func someFunc(paramA: A<SomeTypeSubtypeOfSomeInterface>) 的子类型,因此您可以定义:

B

答案 1 :(得分:1)

一旦开始允许非最终子类,很难表达世界变得多么复杂。如果你可以制作这些最终的类或协议,那么很多尖锐的边缘就会消失。

你说的你想要什么,而你所写的代码并没有真正排队(在处理子类时,非常常见)。所以你真正想要的是重要的。

  

我想检查param是否有类型B作为通用约束。

不确定。这很容易。

class B : SomeInterface {
    func someFunc(param: C) {
        if let typed = param as? A<B> {
            print(typed)
        } else {
            print("NO")
        }
    }
}

这将在我们获得A<B>的任何时候生效。如果我们收到A<SubClassOfB>,即使将其传递给SubclassOfB.someFunc(),它也无效。 (看看我的意思是微妙的?)

从您的代码中,您似乎真的想要&#34;如果我通过A<Self>&#34;在哪里&#34;自我&#34;意味着&#34;完全是我的类,而不是超类或子类。&#34;我见过的唯一方法是使用协议扩展:

extension SomeInterface {
    func someFunc(param: C) {
        if let typed = param as? A<Self> {
            print(typed)
        } else {
            print("NO")
        }
    }
}

这样可以将Self替换为&#34;我的班级。&#34;但请注意,这意味着someFunc(A<MySubclass>)无法正常工作。 A<Self>A<Subclass>不同。请注意,您可以向扩展添加where子句以限制其范围:

extension SomeInterface where Self: B { ... }

如果您的意思是&#34; TSelfSelf&#34;的某些子类,也许它可能,但根据我的经验,它会得到越来越棘手和脆弱。你不能在Swift中对其参数进行协变的泛型类型,因此A<Subclass>本身不是A<Superclass>的子类型(这是一个比它听起来更棘手的问题,你不会& #39;总是希望它是真的)。如果你只是将B标记为最终,这就是一种疯狂的角落案例。然后大部分老鼠的巢都消失了。