我正在尝试构建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()
答案 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()")
}
}
继承ThreeAPI
和FourAPI
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)
如果您不想在saveClient
和FirstAPI
上使用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
方法无法使用。它违反了拥有类型的基本目标。