Having just spent a couple of frustrating days battling with a complex framework with lots of generics involved, I had stumbled across a need to have two generic classes that referred to each other; and, yes, it was very necessary due to strict type checking requirements when the framework gets used outside of the framework.
What I had originally was :
protocol CommandProtocol
{
init()
}
class Command<modelT> : CommandProtocol
{
required init() { }
}
class Model<subjectT, commandT : CommandProtocol>
{
var subject: subjectT
init(subject: subjectT)
{
self.subject = subject
}
// hoping this would avoid having to declare a strictly type command in each model
lazy var command: commandT = .init()
}
// This is where it gets recursive but the compiler doesn't give any errors or even a warning
class StringModelCommand : Command<StringModel>
{
}
class StringModel : Model<String, StringModelCommand>
{
}
It all compile fine, without even a warning but, when you run :
{
let model = StringModel(subject: "Fred")
}
Kaboom !!!
Thread 1: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)
Now, I knew this was likely to be a problem but was surprised when the compiler didn't give me any indication of a possible runtime crash. So I set about finding the best (and neatest) way of sorting this problem.
Here's the resulting code from a long day's effort :
protocol CommandProtocol
{
associatedtype ModelType : ModelProtocol
init()
}
protocol ModelProtocol
{
associatedtype CommandType : CommandProtocol
var command: CommandType { get }
}
class Command<modelT : ModelProtocol> : CommandProtocol
{
typealias ModelType = modelT
required init() { }
}
class Model<subjectT>
{
var subject: subjectT
init(subject: subjectT)
{
self.subject = subject
}
}
class StringCommand : Command<StringModel>
{
}
class StringModel : Model<String>, ModelProtocol
{
lazy var command: StringCommand = .init()
}
So, instead of parameterising the model with the command type, all that is needed is to implement the ModelProtocol and implement the command var in each derived model.
Phew ! I hope this helps someone