swift - 协议(protocol)继承 Swift

标签 swift protocols swift-protocols

我是 swift 协议(protocol)的新手,并尝试通过考虑 Solid 原则来使用它。我采用了两个协议(protocol)(A、B)并将它们与第三个协议(protocol)(D)结合起来。想法是根据需要在另一个类的两个协议(protocol)之间进行选择。检查代码以了解更多信息。

protocol A {
    func fetchA()
}

protocol B {
    func fetchB()
}

protocol D : A,B { }

extension D {
    func fetchB() { }
    func fetchA() {}
}

class B1 : D {
    func fetchB() {
        print("B")
    }
}

class A1 : D {
    func fetchA() {
        print("A")
    }
}

protocol C {
    func fetchC()
}


class C1 : C {
    func fetchC() {
        print("C")
    }
}

enum Ab {
    case a
    case b
}

struct Hello  {
    let first : D
    let second : C
    init(first : D , second :C) {
        self.first = first
        self.second = second
    }
    
    func show(type:Ab){
        switch type {
        case .a:
            first.fetchA()
        case .b:
            first.fetchB()
        }
        second.fetchC()
    }
}

let obj = Hello.init(first: A1(), second: C1())
obj.show(type:.a)

所以当前代码打印“A”。现在,如果我可以将 first 参数更改为 B1() 并 type .b ,它会打印“B”。我想改进代码库并删除 enum 类型,并希望在协议(protocol)的帮助下获得相同的结果。这里需要进行哪些更改?提前致谢。

具体目标:我有 NetworkManger(Class A1)、FirebaseManger(Class B1) 和 LocalDatabaseManger(Class C1)。我想使用 NetworkManger 或 FirebaseManger 进行网络调用,如果失败,则调用 LocalDatabaseManger。

最佳答案

根据您的“具体目标”段落,我相信您目前有这样的目标:

class FirebaseManager {
    func fetchWithFirebase() -> Bool {
        print("Firebase")
        return true
    }
}

class NetworkManager {
    func fetchFromNetwork() -> Bool {
        print("Network")
        return true
    }
}

class LocalDatabaseManager {
    func fetchFromDatabase() -> Bool {
        print("Local")
        return true
    }
}

这三个类不共享任何特定的接口(interface),但都可以以大致相同的方式执行相同的操作。并且您希望某些客户端使用主客户端,如果不能,则使用备份客户端:

class Client {
    let primary: FirebaseManager
    let backup: LocalDatabaseManager
    init(primary: FirebaseManager, backup: LocalDatabaseManager) {
        self.primary = primary
        self.backup = backup
    }

    func show() -> Bool {
        return primary.fetchWithFirebase() || backup.fetchFromDatabase()
    }
}

但是现在 FirebaseMangerLocalDatabaseManger 是硬编码的,更重要的是它们不同的 API 是硬编码的。那么如何解决这个问题呢?

这就是协议(protocol)发挥作用的地方。客户端需要可以获取的东西,即 Fetcher:

protocol Fetcher {
    func fetch() -> Bool
}

如果存在,那么您可以这样编写客户端:

class Client {
    var sources: [Fetcher]
    init(sources: [Fetcher]) {
        self.sources = sources
    }

    func show() -> Bool {
        for source in sources {
            if source.fetch() { return true }
        }
        return false
    }
}

您甚至不必将自己限制在两个来源。你可以列出一份完整的 list ,然后逐一尝试。这很好,但是您的 Manager 中没有一个真正符合 Fetcher。

这就是 Swift 协议(protocol)的强大之处。您可以追溯使类型符合协议(protocol)。您甚至不必控制原始类型。您可以在任何地方执行此操作。

extension FirebaseManager: Fetcher {
    func fetch() -> Bool { fetchWithFirebase() }
}

现在FirebaseManager符合Fetcher,您可以将其传递给客户端。您可以确认其余类型并将它们传递给您的客户:

extension NetworkManager: Fetcher {
    func fetch() -> Bool { fetchFromNetwork() }
}

extension LocalDatabaseManager: Fetcher {
    func fetch() -> Bool { fetchFromDatabase() }
}

let obj = Client(sources: [FirebaseManager(), LocalDatabaseManager()])
obj.show()
// Firebase

根本不需要继承。只需创建一个协议(protocol)来表示您的算法 (show()) 所需的行为,然后扩展每个类型来执行这些行为。

关于swift - 协议(protocol)继承 Swift,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66919926/

相关文章:

swift - 改变触摸按钮的颜色......然后再回来

c# - 理解并创建 Python 协议(protocol)

swift - 如何解决 Swift 协议(protocol)的规范问题

swift - 支持变种!?在协议(protocol)中

c - secret 服务器协议(protocol)保持软件免费

swift - 无法转换具有匹配类型的类型的值 - 我遇到了编译器限制吗?

json - 如何使用 SWIFT 通过 JSON 将数据从多个 View Controller POST 到服务器

ios - 如何在少数情况下包含额外属性的情况下创建枚举

swift - NSSavePanel 名称不是用户可编辑的

ios - 在 Swift 中定义协议(protocol)