2017-08-31 161 views
2

我想在子類雨燕的通用類,但無論我做什麼,編譯器只是不斷抱怨,或者更糟,段錯誤。子類泛型類

這是我編譯它時最接近的,但後來我無法創建子類的實例,因爲編譯器出於某種原因無法推斷出什麼是T

protocol GenericDataSourceCellProtocol { 
    associatedtype ModelType 
    var model: ModelType? {get set} 
} 

struct MyCellState {} 

class MyCell: UITableViewCell, GenericDataSourceCellProtocol { 
    var model: MyCellState? 
} 

class Generic2DDataSource<U, T> 
where U:GenericDataSourceCellProtocol, U:UITableViewCell, T == U.ModelType { 

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


class SubclassedDataSource: Generic2DDataSource<MyCell, MyCellState> {} 

let state = MyCellState() 
let items = [[state]] 
let datasource = SubclassedDataSource(items: items) 
// cannot convert value of type '[Array<MyCellState>]' to expected argument type '[[T]]' 

有沒有辦法讓這項工作?我錯過了什麼?

回答

1

有很多東西會在這裏,極不平凡的雨燕系統的東西。但是,這是你要去的嗎?

protocol GenericDataSourceCellProtocol { 
    associatedtype ModelType 

    var model: ModelType? {get set} 
} 

struct MyCellState {} 

class MyCell: UITableViewCell, GenericDataSourceCellProtocol { 

    typealias ModelType = MyCellState 

    var model: MyCellState? 
} 

class Generic2DDataSource<U> where U: GenericDataSourceCellProtocol, U: UITableViewCell { 

    typealias T = U.ModelType 

    let items: [[T]] 

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


class SubclassedDataSource: Generic2DDataSource<MyCell> { 

} 

let state = MyCellState() 
let items = [[state]] 
let datasource = SubclassedDataSource(items: items) 

而且,我覺得你有什麼應該在技術上是有效的,因爲我發現,如果我是你的代碼改成這樣就會使錯誤消失:

protocol GenericDataSourceCellProtocol { 
    associatedtype ModelType 

    var model: ModelType? {get set} 
} 

struct MyCellState {} 

class MyCell: UITableViewCell, GenericDataSourceCellProtocol { 

    typealias ModelType = MyCellState 

    var model: ModelType? 
} 

class Generic2DDataSource<U, T> where U: GenericDataSourceCellProtocol, U: UITableViewCell, T == U.ModelType { 

    let items: [Array<U.ModelType>] 

    init(items: [Array<U.ModelType>]) { 
     self.items = items 
    } 

    func thing() -> T { 
     let value = items[0][0] 

     return value 
    } 
} 

class SubclassedDataSource: Generic2DDataSource<MyCell, MyCellState> { 
} 

通知我添加了一個功能thing到基類。我這樣做,是因爲在Xcode中,您可以選擇+點擊變量value,它會讓你知道什麼類型的編譯器已經確定它是。在這種情況下,value是類型T即使我指定items[Array<U.ModelType>]。他們應該是相同的,因爲T == U.ModelType,但由於某些原因,它不能在子類編譯過程中弄清楚。

根據你的想法,雖然我認爲T並不是真的必要,因爲你正在形成U和T之間的關係。簡單地提供U作爲通用參數應該是足夠的,就像我的第一個代碼塊一樣。

+0

嘿艾倫,這是一個偉大的答案,它肯定解決問題,謝謝!我很想知道是否有其他人能夠在我的原始示例中提供編譯器行爲的解釋,因此我會等待幾天,然後再將您的答案標記爲已接受。再次感謝,我感謝您抽出時間仔細研究它! – Rog

+0

我也很感興趣。 –

+1

@Rog踢我把你的代碼在Xcode 9B6,它編譯和運行完美,所以它看起來就像是已經固定的編譯器錯誤。 –