2017-05-19 134 views
2

我有一個問題,創建一個便利的初始化方法,然後調用具有泛型類型參數的類上指定的初始化方法。這裏是迅速的3.1版本的XCode 8.3.2(8E2002)操場swift方便初始化和泛型類

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存在,那麼/ *下面的代碼:客戶端* /編譯部分和沒有問題的執行。如果我在便利初始化加我得到以下編譯錯誤:

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

我不認爲這會是一個問題,因爲在便利的init我創建一個結構部分,它實現了協議:以滿足DataSource類的通用約束。便捷init正在執行與客戶端代碼相同的操作,但它無法將[Section]轉換爲[A]。這是一個初始化排序問題嗎?

回答

1

通用佔位符滿足在給定的泛型類型的使用 - 因此你convenience init裏面,你不能假設TSection。這是一個符合A的任意具體類型。

例如,這將是完全合法的呼叫者定義

struct SomeOtherSection : A {...} 

,然後用TSomeOtherSection打電話給你方便初始化器。

在這種情況下,解決方法很簡單,只需將它添加您的方便初始化器在擴展DataSource,其中T被限制於被Section - 所以讓你
通話init(sections:)[Section]

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

太棒了,謝謝你! – user6902806