gpt4 book ai didi

Swift 协议(protocol)要求属性作为协议(protocol)

转载 作者:搜寻专家 更新时间:2023-10-30 23:15:06 25 4
gpt4 key购买 nike

我正在尝试定义一个协议(protocol)“Repository”,它需要定义几个属性(实现特定协议(protocol)“DataSource”)

但由于我的真实场景的复杂性,这些属性之一需要是“DataSource”的子协议(protocol)。

我将问题简化为这个简单的代码:

protocol DataSource { }

protocol ExtraDataSouce: DataSource {
func method1() -> String
}

struct MyDataSource: ExtraDataSouce {
func method1() -> String {
return "whatever"
}
}


protocol Repository {
var firstDataSource: DataSource { get }
var secondDataSource: DataSource { get }
}

struct MyRepository: Repository {
var firstDataSource: DataSource
var secondDataSource: MyDataSource
}

它在编译时返回错误,因为“MyRepository”不符合“Repository”。但我认为它确实如此......知道为什么它不接受定义为“MyDataSource”的“MyRepository”中的“secondDataSource”吗?

最佳答案

经过搜索,我找到了有关您的问题的信息(如果我哪里错了或遗漏了什么,请纠正我):

即使在逻辑上你的代码应该工作,当你在你的 MyRepository 类中声明它们的类型时,swift 编译器不会分离你使用常规或只读协议(protocol)变量的情况。换句话说,如果您在 Repository

中编写,代码中的错误就会变得很明显
var secondDataSource: DataSource { get set }

编译器不会将这种情况分开。我没有找到完全正确的方法来做你想做的事。但是有两种接近的方式:

1) 显而易见且可能是最正确的方法 - 在 MyRepository 中更改 secondDataSource 类型,并根据需要使用其他变量:

var _secondDataSource: MyDataSource
var secondDataSource: DataSource {
get {return _secondDataSource}
set {
guard let newValue = newValue as? MyDataSource else {
fatalError("MyRepository: attempt to set DataSource type, MyDataSource type expected")
}
_secondDataSource = newValue
}
}

2) 协议(protocol)方式的关联类型。在这里我将改进@RaduNunu 的答案,因为他的代码中的 associatedtype type = DataSource 行只有占位符效果,他的解决方案允许您选择采用任何类型的 secondDataSource , String 例如:

protocol Repository {
associatedtype Type = DataSource
var firstDataSource: DataSource { get }
var secondDataSource: Type { get }
}

struct MyRepository: Repository {
var firstDataSource: DataSource
var secondDataSource: String // - this is ok!
}

这段代码可以编译并运行,但看起来很糟糕。相反类型占位符你最好使用协议(protocol)一致性:

protocol Repository {
associatedtype Type: DataSource
var firstDataSource: DataSource { get }
var secondDataSource: Type { get }
}

struct MyRepository: Repository {
var firstDataSource: DataSource
//var secondDataSource: String - this line not allowed now
var secondDataSource: MyDataSource
}

这段代码已经非常接近目标了。但是,从现在开始你不能使用协议(protocol)作为关联类型,所以声明

var secondDataSource: DataSource

MyRepository 中将不起作用。这是使用关联类型的代价:您只能使用符合 DataSource 的类/枚举/结构类型。

关于Swift 协议(protocol)要求属性作为协议(protocol),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38007881/

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