Reputation: 357
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".
Upvotes: 4
Views: 1500
Reputation: 270945
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. 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.
"Okay, why not just use Any
for that type?" 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
:
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)]
Upvotes: 4
Reputation: 51882
You need to tell the compiler what the implemented type of T is
let sections = [Section<GenericRow<String>>]()
or like this
typealias SectionType = Section<GenericRow<String>>
let sections = [SectionType]()
Upvotes: 0