I have a pretty complicated structure with Generic types
in my app. This works, but there is an issue, that at the end of this chain, I need to specify some types 2 times, because they need to be used as generics of some class, and one of these generic types, also need generic type. Which are always the same types as these before it. It goes like this <A, B, C<A, B>>
This makes it a little unpleasant to use. Is there some way to make it infer A
and B
from C
Here is sample code, with stripped functionalities:
// MARK: - Base classes that Im using, stripped from funcionalities.
// This one is a base for performing some detection. It can return any type as a result of scanning.
class DetectionPerformer<ResultType> {}
// This one adds possibility to load some model needed to perform scanning from the disk.
class LocalFileDetectionPerformer<ResultType, LocalModelType>: DetectionPerformer<ResultType> {
required init(localModelURL: URL) {}
}
// This one adds possibility to download this model and store it on the disk before loading.
class DownloadableDetectionPerformer<ResultType, LocalModelType>: LocalFileDetectionPerformer<ResultType, LocalModelType> {}
// This one wraps LocalFileDetectionPerformer inside DownloadableDetectionPerformer, and use them together.
class RemoteFileDetectionPerformer<ResultType, LocalModelType, LocalFileDetectionPerformerType: DownloadableDetectionPerformer<ResultType, LocalModelType>>: DetectionPerformer<ResultType> {
private let localFileDetectionPerformer: LocalFileDetectionPerformerType
init(remoteModelURL: URL) {
let localModelURL = Self.localModelURL(for: remoteModelURL)
localFileDetectionPerformer = LocalFileDetectionPerformerType(localModelURL: localModelURL)
}
static func localModelURL(for url: URL) -> URL {
url.appendingPathExtension("local")
}
}
// Detector is main object in application. It takes some type of Detector as init parameter, and works on it.
class Detector<ResultType, DetectionPerformerType: DetectionPerformer<ResultType>> {
let performer: DetectionPerformerType
init(performer: DetectionPerformerType) {
self.performer = performer
}
}
// Now I can implement some specific performers, whcich will do real work. For example:
class SamplePerformer: DownloadableDetectionPerformer<Int, String> {}
// And I'm able to create Detector with any type of Performer:
let detectorA = Detector(performer: SamplePerformer(localModelURL: URL(string: "")!))
// The problem begins, when I want to wrap Performer into RemoteFileDetectionPerformer
let detectorB = Detector(performer: RemoteFileDetectionPerformer<Int, String, SamplePerformer>(remoteModelURL: URL(string: "")!))
// Here I need to specify all 3 generic types of RemoteFileDetectionPerformer, even tough two first are always the same as generic types of SamplePerformer. I can't even specify different ones, as this would create an error.
// Is there some way for RemoteFileDetectionPerformer to infer these first two generic types from LocalFileDetectionPerformerType? Maybe I need to construct these some differently?