【问题标题】:Swift Array of Class Types that Each Conform to a Protocol and are Subclasses of Common ClassSwift 类类型数组,每个都符合协议并且是公共类的子类
【发布时间】:2017-11-27 17:07:16
【问题描述】:

我在 Swift 中有一个带有表单签名的方法:

func myMethod<T>(class: T.Type) where T: SomeClass & MyProtocol

我想要一个变量,它是一个类数组,它们都是 SomeClass 的子类并符合 MyProtocol。

它看起来像:

let classArray = [SubclassOfSomeClass.self, SubclassTwoOfSomeClass.self, SubclassThreeOfSomeClass.self]

SubclassOfSomeClass、SubclassTwoOfSomeClass 和 SubclassThreeOfSomeClass 都符合 MyProtocol

然后我想拨打myMethod如下:

classArray.forEach { classType in

    myMethod(class: classType)
}

我收到编译器错误“无法推断通用参数 T”。这对我来说很有意义,因为classArray 变量的类型被推断为[MyClass.Type]

我的问题是,我可以以及如何定义变量classArray,以便编译器知道其中定义的每个类型都符合协议MyProtocol

【问题讨论】:

    标签: swift


    【解决方案1】:

    您可以通过使SomeClass 符合MyProtocol 来实现这一点。因此每个子类也必须符合MyProtocol

    那么你的方法签名就是:

    func myMethod<T>(class: T.Type) where T: SomeClass
    

    如果不需要,那么您可以将 myMethod 的类型更改为不是通用的。我认为 swift 无法键入具有 (SomeClass & MyProtocol).Type 的元素的数组。在您的情况下,您并没有真正使用通用对象。您确实有一个特定的类型,它是(SomeClass &amp; MyProtocol).Type。您的代码将如下所示:

    protocol MyProtocol: class {
    
    }
    
    class SomeClass: NSObject {
    
    }
    
    class SubClass: SomeClass, MyProtocol {
    
    }
    
    class SubClass2: SomeClass, MyProtocol {
    
    }
    
    let classArray: [(SomeClass & MyProtocol).Type] = [SubClass.self, SubClass2.self]
    
    func myMethod(class: (SomeClass & MyProtocol).Type) {
    
    }
    
    classArray.forEach {
        myMethod(class: $0)
    }
    

    【讨论】:

    • 确实如此,但并非 SomeClass 上的所有子类都符合 MyProtocol,因此很遗憾这不是一个选项。
    • 你可以检查我的编辑。我只是不认为你可以像你描述的那样使用泛型。
    • 感谢您的努力,但 [SubClass(), SubClass2()] 是类实例的数组,而不是 [SomeClass.Type]。如果不能按照描述使用泛型,这是一个完全可以接受的答案。
    • 啊,我误会了。您也可以在类型上执行此操作。再次更新。
    【解决方案2】:
    protocol MyProtocol {
       var x: Int { get }
    }
    
    class MyClass: NSObject {
        var y: Int = 10
    }
    
    class SubClass1: MyClass, MyProtocol {
        private(set) var x: Int = 9
    }
    
    class SubClass2: MyClass {
    }
    
    class SubClass3: MyClass, MyProtocol {
        var x: Int { return 15 }
    }
    
    let items: [MyClass & MyProtocol] = [SubClass1(), SubClass3()]
    
    func myMethod(_ item: MyClass & MyProtocol) {}
    
    classArray.forEach { myMethod($0) }
    

    所以现在你可以只使用 MyClass & MyProtocol

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-11-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-02-06
      • 1970-01-01
      相关资源
      最近更新 更多