我遇到了Swift中的协议继承问题。我正在尝试构建一个接受协议类型X数组的API。此API的消费者应该能够传入任何类型的协议类型X或从协议X继承的任何子协议类型X'。这似乎可以 - 如果没有某种形式将协议类型X'显式地转换回协议类型X,则无法在Swift中实现。为什么会出现这种情况?我没有看到类型的这种行为(我怀疑它可能是因为继承的工作方式明显不同)。
这是我的代码:
public protocol InjectableService
{}
public protocol ClientDependency
{
func serviceDependencies() -> [InjectableService.Type]
func injectDependencies(dependencies: [InjectableService])
}
public protocol TouchIdServiceInterface : InjectableService
{
func biometricAuthenticate() -> Void
}
public protocol PasswordServiceInterface : InjectableService
{
func passwordAuthenticate() -> Void
}
public class LoginController : ClientDependency
{
private var services: [InjectableService]!
public func injectDependencies(dependencies: [InjectableService]) {
services = dependencies
}
public func serviceDependencies() -> [InjectableService.Type] {
return [TouchIdServiceInterface.self as! InjectableService.Type , PasswordServiceInterface.self as! InjectableService.Type]
}
}
正如您在上面的函数serviceDependencies()中所看到的,我必须将子协议类型奇怪地转换回其超级协议类型。如果我删除了演员,我会明确地要求我做一个编译器警告。
有什么方法可以避免这种情况吗?我喜欢它的类型,它可以为你解决。我真的想避免这个转换问题,因为它会使API非常笨重。谢谢!
答案 0 :(得分:0)
来自Apple文档:
元数据类型
元类型类型是指任何类型的类型,包括类类型, 结构类型,枚举类型和协议类型。
类,结构或枚举类型的元类型是其名称 该类型后跟
.Type
。协议类型的元类型 - 不是 在运行时符合协议的具体类型是名称 该协议后跟.Protocol
。例如,元的类型 类类型SomeClass是SomeClass.Type
和元类型 协议SomeProtocol是SomeProtocol.Protocol
。您可以使用postfix
self
表达式将类型作为值进行访问。 例如,SomeClass.self
返回SomeClass本身,而不是实例 SomeClass。并且SomeProtocol.self
返回SomeProtocol本身,而不是 一个在运行时符合SomeProtocol的类型的实例。
如果要返回[InjectableService.Type]
,则需要定义每个协议的类。
public protocol InjectableService
{}
public protocol ClientDependency
{
func injectDependencies(dependencies: [InjectableService])
func serviceDependencies() -> [InjectableService.Type]
}
public protocol TouchIdServiceInterface : InjectableService
{
func biometricAuthenticate() -> Void
}
public protocol PasswordServiceInterface : InjectableService
{
func passwordAuthenticate() -> Void
}
public class TouchIdService: TouchIdServiceInterface {
public func biometricAuthenticate() -> Void { }
}
public class PasswordService: PasswordServiceInterface {
public func passwordAuthenticate() -> Void { }
}
public class LoginController: ClientDependency
{
private var services: [InjectableService]!
public func injectDependencies(dependencies: [InjectableService]) {
services = dependencies
}
public func serviceDependencies() -> [InjectableService.Type] {
let ts: [InjectableService.Type] = [
TouchIdService.self,
PasswordService.self
]
return ts
}
}
let controller = LoginController()
let services = controller.serviceDependencies()
<强>已更新强>
public protocol ClientDependency
{
func injectDependencies(dependencies: [InjectableService])
func serviceDependencies() -> [Any]
}
的LoginController:
public func serviceDependencies() -> [Any] {
let ts: [Any] = [
TouchIdServiceInterface.self,
TouchIdServiceInterface.self
]
return ts
}
测试:
let controller = LoginController()
let services = controller.serviceDependencies()
if let touchIdService = services.first as? TouchIdServiceInterface.Protocol {
print(touchIdService)
}