I need to instantiate a class with generics. What I came up with is a straightforward a bit ugly solution only. I wonder whether more elegant solution exists or not. What I want to achieve in a real app is to instantiate different implementations that have generics parameters based on the settings in the UserDefaults.
There are two problems:
- How to refer to generics in the properties?
- How to instantiate generics with dynamic type binding?
import UIKit
protocol Joint {
associatedtype T
var count: T { get }
}
class SingleJoint: Joint {
var count: Float {
1
}
}
class MultipleJoints: Joint {
var count: Int {
10
}
}
// Ugly solution
class ViewModel1 {
var singleJoint: SingleJoint? = nil
var multipleJoints: MultipleJoints? = nil
private var decisionMakeCondition: Bool {
true
}
var joints: String {
if self.decisionMakeCondition {
return String(singleJoint?.count ?? 0)
} else {
return String(multipleJoints?.count ?? 0)
}
}
init() {
if self.decisionMakeCondition {
singleJoint = SingleJoint()
} else {
multipleJoints = MultipleJoints()
}
}
}
// Might be a more elegant solution but it does not compile (
class ViewModel2<J: Joint> {
var joints: String {
"\(joint.count)"
}
private let joint: J!
private var decisionMakeCondition: Bool {
true
}
init() {
// Problem 2. How to instantiate a type with generics?
// Different implementations might be instantiated based on a condition
if self.decisionMakeCondition {
joint = SingleJoint()
} else {
joint = MultipleJoints()
}
}
}
// I want to avoid introducing generic types here i.e. ```ViewController<T: Joint>: UIViewController```
class ViewController: UIViewController {
// Problem 1. How to refer to the type with generics?
let model = ViewModel2()
//let model = ViewModel1()
func test() {
print("Joints \(model.joints)")
}
}
let controller = ViewController()
controller.test()