2

我被困在 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 变得非常笨拙。谢谢!

4

1 回答 1

0

来自苹果文档:

元类型

元类型类型是指任何类型的类型,包括类类型、结构类型、枚举类型和协议类型。

类、结构或枚举类型的元类型是该类型的名称,后跟.Type. 协议类型的元类型(不是在运行时符合协议的具体类型)是该协议的名称,后跟.Protocol. 例如,类类型 SomeClass 的元类型是SomeClass.Type,协议 SomeProtocol 的元类型是SomeProtocol.Protocol

您可以使用后缀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]
}

登录控制器:

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)
}
于 2017-01-03T02:37:24.627 回答