简体   繁体   English

如何快速创建通用关联类型协议的数组?

[英]How to create array of generic associated type protocol in swift?

Better to ask with example. 最好举个例子。 So its table sections and rows 所以它的表部分和行

First created a protocol which needs to be implemented by all rows which has an associated type, must be given by caller to tell while defining row. 首先创建一个协议,该协议必须由具有关联类型的所有行实现,调用方必须在给定行时告诉它。

protocol RowElementProtocol {
    associatedtype ElementType
    var cellIdentifier: String {get set}
    var cellType: ElementType {get set}
}

So creating a generic row struct here 所以在这里创建一个通用的行结构

struct GenericRow <T>: RowElementProtocol {

    var cellIdentifier = "cell"
    var cellType: T

    /// Some Other Properties

    init(cellIdentifier: String = "cell", cellType: T) {

        self.cellIdentifier = cellIdentifier
        self.cellType = cellType
    }
}

Creating a different row struct here 在这里创建一个不同的行结构

struct DifferentRow<T>: RowElementProtocol {

    var cellIdentifier = "cell"
    var cellType: T

    /// Some Different Properties other then generic
}

Now creating a section which can have any kind of rows 现在创建一个可以包含任何行的节

struct Section<T: RowElementProtocol> {

    var rows = 1
    var rowElements: [T]
}

Everything is fine here, Problem arises when I want to initialise an array of sections 一切都很好,当我想初始化一个节数组时出现问题

let sections = [Section<T: RowElementProtocol>]()

Compiler is not allowing me to initialise. 编译器不允许我初始化。 Its showing ">' is not a postfix unary operator". 其显示的“>'不是后缀一元运算符”。

You need to tell the compiler what the implemented type of T is 您需要告诉编译器T的实现类型是什么

let sections = [Section<GenericRow<String>>]()

or like this 或像这样

typealias SectionType = Section<GenericRow<String>>
let sections = [SectionType]()

Let's have a look at the consequences of the compiler allowing you to create such an array. 让我们看一下允许您创建此类数组的编译器的结果。

You could do something like this: 您可以执行以下操作:

var sections = [Section<T: RowElementProtocol>]()
var sec1 = Section<GenericRow<String>>()
var sec2 = Section<DifferentRow<Int>>()
sections.append(sec1)
sections.append(sec2)
let foo = sections[0] // how can the compiler know what type this is?

See the problem now? 现在看到问题了吗? "Well, foo can just be of type Section<T: RowElementProtocol> " you might say. 您可能会说Section<T: RowElementProtocol> “好吧, foo可以是Section<T: RowElementProtocol>类型。” Okay, let's suppose that's true: 好吧,让我们假设这是真的:

foo.rowElements[0].cellType // what the heck is the type of this?

The compiler has no idea. 编译器不知道。 It only knows that foo.rowElements[0] is "some type that conforms to RowElementProtocol but cellType could be anything. 它只知道foo.rowElements[0]是“符合RowElementProtocol某种类型,但是cellType可以是任何类型。

"Okay, why not just use Any for that type?" “好吧,为什么不只对这种类型使用Any ?” you might ask. 你可能会问。 The compiler could do this, but that makes your generics pointless, doesn't it? 编译器可以做到这一点,但这使您的泛型毫无意义,不是吗?

If you want to make your generics pointless, you can do what's called "type erasure", by creating the types AnyRowElement and AnySection : 如果你使你的仿制药没有意义的,你可以做什么叫做“类型擦除”,通过创建类型AnyRowElementAnySection

struct AnyRowElement : RowElementProtocol {
    var cellIdentifier: String

    var cellType: Any

    typealias ElementType = Any

    init<T: RowElementProtocol>(_ x: T) {
        self.cellIdentifier = x.cellIdentifier
        self.cellType = x.cellType
    }
}

struct AnySection {
    var rows: Int
    var rowElements: [AnyRowElement]

    init<T: RowElementProtocol>(_ x: Section<T>) {
        self.rows = x.rows
        self.rowElements = x.rowElements.map(AnyRowElement.init)
    }
}

let sections: [AnySection] = [AnySection(sec1), AnySection(sec2)]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM