相同的协议对象,但功能不相同

时间:2019-05-22 10:40:24

标签: swift design-patterns

我正在尝试构建API模式。

我有几种不同的API,其中有些具有相同的功能,有些还具有其他API不能访问的其他功能。

协议的问题在于它们都可以访问。如果未覆盖该功能,如何限制访问权限?

apiRequest:

class APIRequest {
    static func loginCli(completion: (UserClinic) -> ()) {

    }

    static func loginFami(completion: (User) -> ()) {

    }

    static func loginDavid(completion: (UserDavid) -> ()) {

    }
}

协议和API:

protocol API {
    func login<T>(completion: (T) -> ())
    func saveClient()
}

extension API {
    func saveClient() {
        saveClient()
    }
}

class FirstAPI: API {
    func login<T>(completion: (T) -> ()) {
        APIRequest.loginFami { (user) in

        }
    }
}

class SecondAPI: API {
    func login<T>(completion: (T) -> ()) {
        APIRequest.loginCli { (user) in

        }
    }
}

class ThreeAPI: API {
    func login<T>(completion: (T) -> ()) {
        APIRequest.loginDavid { (user) in

        }
    }

    func saveClient() {
        // Save client
    }
}

查看模型:

class LoginViewModel {
    var apiClient: API

    init() {
        // Below its good
        apiClient = ThreeAPI()
        apiClient.saveClient()

        // Below its not good
        apiClient = FirstAPI()
        apiClient.saveClient() // I want this is not accessible

        // Below its good
        apiClient = SecondAPI()
        apiClient.saveClient() // I want this is not accessible
    }
}

就我而言,我只需要第三个API即可访问函数saveClient()

3 个答案:

答案 0 :(得分:0)

尝试一下。

protocol API {
    func login<T>(completion: (T) -> ())
}

extension API where Self: ThreeAPI {
    func saveClient() {

    }
}

在以上代码中,protocol API extension仅适用于ThreeAPI类型的对象。

我直接在这里使用ThreeAPI。您可以为所有需要common type的{​​{1}}制作一个classes,并使用该类型代替saveClient()

用法:

ThreeAPI

编辑1:

为所有需要使用apiClient = ThreeAPI() (apiClient as? ThreeAPI)?.saveClient() apiClient = FirstAPI() //saveClient() not available apiClient = SecondAPI() //saveClient() not available 方法的类创建一个CommonAPI父级class

saveClient()

class CommonAPI { func saveClient() { print("CommonAPI saveClient()") } } 继承ThreeAPIFourAPI

CommonAPI

只需使用class ThreeAPI: CommonAPI, API { func login<T>(completion: (T) -> ()) { } override func saveClient() { print("ThreeAPI saveClient()") } } class FourAPI: CommonAPI, API { func login<T>(completion: (T) -> ()) { } override func saveClient() { print("FourAPI saveClient()") } } 来调用switch statement类型的所有对象上的saveClient()

CommonAPI

在这种情况下,您无需解析每种类型。

答案 1 :(得分:0)

如果您不想在saveClientFirstAPI上使用SecondAPI方法,则需要将该方法提取到单独的协议中。像这样:

protocol APIThatCanLogin {
    func login<T>(completion: (T) -> ())
}

protocol APIThatCanSave {
    func saveClient()
}


class FirstAPI: APIThatCanLogin { }
class SecondAPI: APIThatCanLogin { }
class ThreeAPI: APIThatCanLogin, APIThatCanSave { }

但是也许您应该重新考虑使用协议。至少在此示例中,它没有任何好处。

答案 2 :(得分:0)

如上所述,将不会有解决方案。 API类型表示“具有以下方法和属性”。您不能将某些东西分配给类型API的变量,然后说“但它没有某些方法”。这违反了LSP,后者是这类类型的基础。考虑以下代码:

func save(api: API) {
    api.saveClient()
}

如果您要描述的功能可以实现,是否可以编译?如果它确实编译了,然后用FirstAPI()调用了,那该怎么办?

如果您希望saveClient成为无操作人员(不做任何事情),那么这很简单。提供一个空的默认实现:

extension API {
    func saveClient() {}
}

如果您希望某些API可保存,而某些API不可用,那么这也很简单:

protocol API {
    func login<T>(completion: (T) -> ())
}

protocol SavableAPI: API {
    func saveClient()
}

但是您编写的init方法无法使用。它违反了拥有类型的基本目标。