swift便利init和泛型类

swift便利init和泛型类,swift,generics,init,Swift,Generics,Init,我在创建一个方便的init方法时遇到了一个问题,该方法随后调用一个具有泛型类型参数的类上的指定init。这里是swift 3.1 XCode版本8.3.2(8E2002)游戏场 protocol A { var items: [String] { get set } func doSomething() } struct Section : A { var items: [String] = [] func doSomething() { pr

我在创建一个方便的init方法时遇到了一个问题,该方法随后调用一个具有泛型类型参数的类上的指定init。这里是swift 3.1 XCode版本8.3.2(8E2002)游戏场

protocol A {
    var items: [String] { get set }
    func doSomething()
}

struct Section : A {
    var items: [String] = []

    func doSomething() {
        print("doSomething")
        items.forEach { print($0) }
    }
}

class DataSource<T: A> {
    var sections: [T]

    init(sections: [T]) {
        self.sections = sections
    }

    func process() {
        sections.forEach { $0.doSomething() }
    }

    convenience init() {
        var section = Section()
        section.items.append("Goodbye")
        section.items.append("Swift")

        self.init(sections: [section])
    }
}

/*: Client */
var section = Section()
section.items.append("Hello")
section.items.append("Swift")

let ds = DataSource(sections: [section])
ds.process()

我不认为这是一个问题,因为在便利初始化中,我创建了一个节结构,它实现了协议a,该协议满足DataSource类的通用约束。便利init执行与客户端代码相同的操作,但无法将[Section]转换为[a]。这是一个初始化排序问题吗?

通用占位符在使用给定的通用类型时得到满足–因此在
便利初始化
中,您不能假定
T
。它是符合
A
的任意具体类型

例如,调用方定义

struct SomeOtherSection : A {...}
然后用
T
being
SomeOtherSection
调用您的便利初始化器

本例中的解决方案很简单,您只需在
数据源
的扩展中添加方便的初始化器,
T
被限制为
–因此允许您使用
[节]
调用
init(节:)

extension DataSource where T == Section {

    convenience init() {
        var section = Section()
        section.items.append("Goodbye")
        section.items.append("Swift")

        self.init(sections: [section])
    }
}

// ...

// compiler will infer that T == Section here.
let ds = DataSource()
extension DataSource where T == Section {

    convenience init() {
        var section = Section()
        section.items.append("Goodbye")
        section.items.append("Swift")

        self.init(sections: [section])
    }
}

// ...

// compiler will infer that T == Section here.
let ds = DataSource()