gpt4 book ai didi

swift - 多个协议(protocol)扩展中的功能不明确?

转载 作者:可可西里 更新时间:2023-11-01 01:36:31 25 4
gpt4 key购买 nike

我有多个具有相同函数名称的协议(protocol)。某些协议(protocol)具有关联类型,我无法像在非通用协议(protocol)中那样弄清楚如何调用这些函数。我收到错误:Protocol 'MyProtocol1' can only be used as a generic contraint because it has Self or associated type requirements

这是我正在尝试做的事情:

protocol Serviceable {
associatedtype DataType
func get(handler: ([DataType] -> Void)?)
}

struct PostService: Serviceable {
func get(handler: ([String] -> Void)? = nil) {
print("Do something...")
}
}

protocol MyProtocol1: class {
associatedtype ServiceType: Serviceable
var service: ServiceType { get }
}

extension MyProtocol1 {
func didLoad(delegate: Self) {
print("MyProtocol1.didLoad()")
}
}

protocol MyProtocol2: class {

}

extension MyProtocol2 {
func didLoad(delegate: MyProtocol2) {
print("MyProtocol2.didLoad()")
}
}

class MyViewController: UIViewController, MyProtocol1, MyProtocol2 {
let service = PostService()

override func viewDidLoad() {
super.viewDidLoad()
didLoad(self as MyProtocol1) // Error here: Protocol 'MyProtocol1' can only be used as a generic contraint because it has Self or associated type requirements
didLoad(self as MyProtocol2)
}
}

如何从通用协议(protocol)扩展中专门调用该函数?

最佳答案

通过将协议(protocol)变成通用协议(protocol)(见下文)或创建一个 type eraser 很容易实现对于这些协议(protocol),但这非常强烈地表明您有设计问题,您应该重新设计您的类和/或扩展。像这样的冲突强烈表明 MyStruct 本身做了太多事情,因为它被 MyProtocol1MyProtocol2 拉向多个方向。这里应该有两个对象。 (组合而不是继承。)

class MyStruct: MyProtocol1, MyProtocol2 {
let service = PostService()

func prot1Load<T: MyProtocol1>(t: T) {
t.didLoad()
}

func prot2Load<T: MyProtocol2>(t: T) {
t.didLoad()
}
init() {
prot1Load(self)
prot2Load(self)
}
}

对于您在评论中的特定示例,我会使用组合而不是继承。您将协议(protocol)视为多重继承,这几乎是不对的。而是用符合协议(protocol)的东西组成。

protocol LoadProviding {
func load()
}

struct MyLoader1: LoadProviding {
func load() {
print("MyLoader1.didLoad()")
}
}

struct MyLoader2: LoadProviding {
func load() {
print("MyLoader2.didLoad()")
}
}

protocol Loader {
var loaders: [LoadProviding] { get }
}

extension Loader {
func loadAll() {
for loader in loaders {
loader.load()
}
}
}

class MyStruct: Loader {
let service = PostService()
let loaders: [LoadProviding] = [MyLoader1(), MyLoader2()]

init() {
loadAll()
}
}

当然,您并不一定要让 LoadProviding 成为一个完整的结构。如果这就是您所需要的,它可能只是一个函数:

typealias LoadProviding = () -> Void

func myLoader1() {
print("MyLoader1.didLoad()")
}

func myLoader2() {
print("MyLoader2.didLoad()")
}

protocol Loader {
var loaders: [LoadProviding] { get }
}

extension Loader {
func loadAll() {
for loader in loaders {
loader()
}
}
}

class MyStruct: Loader {
let service = PostService()
let loaders: [LoadProviding] = [myLoader1, myLoader2]

init() {
loadAll()
}
}

如果您有时间浏览有关该主题的视频,您可能会对 Beyond Crusty: Real World Protocols 感兴趣来自 dotSwift 的谈话。这是关于这个和类似的问题。

关于swift - 多个协议(protocol)扩展中的功能不明确?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36841399/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com