协议继承 Swift

Protocols inheritance Swift

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

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 类型,并希望在协议的帮助下获得相同的结果。需要在此处进行哪些更改。?提前致谢。

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

一种方法是在符合 D 时添加额外的要求,即您指定要使用的方法。

protocol D : A,B {
    func fetch()
}

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

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

struct Hello  {
    let first : D
    let second : C
    
    func show(){
        first.fetch()
        second.fetchC()
    }
}

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

但这可能不是最好的方法,具体取决于这些协议和 类 实际上应该代表什么。

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

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
    }
}

三个 类 不共享任何特定界面,但都可以以大致相同的方式做同样的事情。并且您希望某些客户端使用主客户端,如果不能则使用备用客户端:

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 是硬编码的。那么如何解决呢?

这就是协议的用武之地。客户端需要一些可以获取的东西,一个 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
    }
}

您甚至不必将自己局限于两个来源。你可以列出一个完整的清单,然后一个接一个地尝试。这很好,但是 none 的经理实际上符合 Fetcher。

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

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

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