首页 文章

swift便利init和泛型类

提问于
浏览
3

我在创建一个方便的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()

如果不存在便利init,那么/ *:Client * /部分下面的代码将编译并执行而不会出现问题 . 如果我添加了方便init,我得到以下编译错误:

cannot convert value of type '[Section]' to expected argument type '[_]'
        self.init(sections: [section])

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

1 回答

  • 5

    通用占位符对给定泛型类型的使用感到满意 - 因此在 convenience init 中,您不能假设 TSection . 它是符合 A 的任意具体类型 .

    例如,调用者定义a是完全合法的

    struct SomeOtherSection : A {...}
    

    然后使用 T SomeOtherSection 调用您的便利初始化程序 .

    在这种情况下的解决方案很简单,您只需在 DataSource 的扩展名中添加便利初始化程序,其中 T 被限制为 Section - 因此允许您
    使用 [Section] 调用 init(sections:)

    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()
    

相关问题