TL:DR
How can I make this compile so the protocol can be applied to any concrete implementations of BaseObject, specifically so it can access someFuncUnrelatedToTypeConstraint (that's the real goal)?
@interface BaseObject <__covariant TypeConstraint> : NSObject
- (TestObject*)someFuncUnrelatedToTypeConstraint;
@end
protocol ProtocolOnlyApplicableToBaseObject : BaseObject {}
Note: This won't compile because it complains I need to specify the type parameter for BaseObject, but that's just it... I want this to apply to any/all BaseObject<T> types regardless of what T is.
Now the full code...
In our ObjC codebase, we have a concrete object and a generic defined like so (oversimplified for the example). This says only NSObject or one of its subclasses can satisfy the type requirement.
@interface TestObject : NSObject
@end
@interface BaseObject <__covariant TypeConstraint> : NSObject
- (TestObject*)someFuncUnrelatedToTypeConstraint;
@end
We also have these (again, oversimplified) ObjC subclasses, the last which omits the type, so it defaults to NSObject implicitly.
@interface ConcreteObjectA : BaseObject<UIView>
@end
@interface ConcreteObjectB : BaseObject<UIWindow>
@end
@interface ConcreteObjectC : BaseObject
@end
Now we're trying to write a Swift protocol and a paired extension that can only be applied to instances of BaseObject because the extension needs to call the function someFuncUnrelatedToTypeConstraint().
protocol ProtocolForBaseObject : BaseObject {
associatedtype ReturnType:SomeTypeAcceptingTestObject
}
extension ProtocolForBaseObject {
func someTest() -> ReturnType {
let testObject = self.someFuncUnrelatedToTypeConstraint()
return ReturnType(testObject)
}
}
The goal is so we can call this in Swift...
extension ConcreteObjectA : ProtocolForBaseObject {
typealias ReturnType = ReturnTypeA
}
let objA = ConcreteObjectA()
let returnTypeA = objA.someTest()
extension ConcreteObjectB : ProtocolForBaseObject {
typealias ReturnType = ReturnTypeB
}
let objB = ConcreteObjectB()
let returnTypeB = objB.someTest()
extension ConcreteObjectC : ProtocolForBaseObject {
typealias ReturnType = ReturnTypeC
}
let objC = ConcreteObjectC()
let returnTypeC = objC.someTest()
The issue is ProtocolForBaseObject won't compile because it says I have to specify the generic type constraint...
Reference to generic type 'BaseObject' requires arguments in <...>
But the issue is I don't care what the type constraint for the generic is. I want this to apply to all instances of the generic as the function I'm trying to reach doesn't use that type anyway so there's no reason for the protocol to care what that type is.
To get around it, I tried adding NSObject as the type constraint, but this doesn't seem to work either since BaseObject<NSObject> != BaseObject<UIView> even though UIView is a subclass of NSObject.
protocol ProtocolForBaseObject : BaseObject<NSObject> {}
So how can you structure the protocol to apply to all concrete instances of the BaseObject generic, regardless of the type constraint?