winstonp
(Winston)
1
I want to define a protocol and some classes like this:
protocol AppleDevices {
associatedtype DelegateProtocol: AppleDevicesDelegate
var delegate: DelegateProtocol! { get }
init(delegate: DelegateProtocol)
}
protocol AppleDevicesDelegate { ... }
class IPhone: AppleDevices {
weak var delegate: IPhoneDelegate! // instead of AppleDeviceDelegate where someone could accidentally assign say, MacDelegate to this class
init(delegate: IPhoneDelegate) { ... }
}
protocol IPhoneDelegate: AppleDevicesDelegate { … }
The compiler complains that the class IPhone does not conform to its protocol because, to my understanding, the associatedtype of a protocol implementation cannot be a subprotocol of some other protocol. As in, the above code works if IPhoneDelegate was a class, not another protocol.
As far as I understand it, the design I would like to achieve above is not currently possible in the Swift compiler.
1 Like
You can not use an existential as a type conforming to that protocol. If you change the class to be generic over an AppleDevicesDelegate it would work because you're now using a concrete type.
class IPhone<Delegate: IPhoneDelegate>: AppleDevices {
weak var delegate: Delegate!
}
That would work.
1 Like
AlexanderM
(Alexander Momchilov)
3
Putting an explicit typealias for the associated type (rather than leaving it to be inferred from the parameter of the init) gives a better error message:
class IPhone: AppleDevices {
// ❌ possibly intended match 'IPhone.DelegateProtocol' (aka 'any IPhoneDelegate')
// does not conform to 'AppleDevicesDelegate'
typealias DelegateProtocol = any IPhoneDelegate
weak var delegate: IPhoneDelegate!
init(delegate: IPhoneDelegate) { }
}
I still don't quite understand why it doesn't conform. Can someone please elaborate?