class BaseCellModel {}
class BaseCell<Model: BaseCellModel>: NSObject {
var model: Model? { nil }
}
class DerivedCellModel: BaseCellModel {}
class DerivedCell: BaseCell<DerivedCellModel> {}
let cell: NSObject = DerivedCell()
// Challenge: Cast cell to BaseCell so that we can access cell.model
let r1 = cell as? BaseCell // ❌
let r2 = cell as? BaseCell<BaseCellModel> // ❌
let r3 = cell as? BaseCell<DerivedCellModel> // ✅
let r4 = cell as? DerivedCell // ✅
Is there a way to access cell.model without knowing the concrete Derived* type as there may have many subclass type?
AFAIK, Swift does not support covariance or contra-variance regarding to generic parameters. (There are exceptions in the standard library which are specially handled, like Array)
That is to say, commonly speaking, given a generic type G<T>, if A is a subtype of B, then currently there's no relation between G<A> and G<B> in Swift.
In your case, I would model a type-erased base class so that most of the operations can be defined on it. (Of course it can be defined as a protocol, just like the way you did, but I believe some type-erasing would be required eventually)
class AbstraceCell {
var abstractModel: BaseCellModel { get }
}
class BaseCell<Model: BaseCellModel>: AbstraceCell {
var model: Model { get }
}
class DerivedCell: BaseCell<DerivedCellModel> { }