我是 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()
}
}
但是现在 FirebaseManger
和 LocalDatabaseManger
是硬编码的,更重要的是它们不同的 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/