Swift 无法使用匹配的类型转换类型的值-我是否已达到编译器限制?
背景: 我正在构建一个带有服务层的应用程序,它应该返回相似的模型(例如,所有模型都有一个Swift 无法使用匹配的类型转换类型的值-我是否已达到编译器限制?,swift,compiler-errors,swift-protocols,Swift,Compiler Errors,Swift Protocols,背景: 我正在构建一个带有服务层的应用程序,它应该返回相似的模型(例如,所有模型都有一个text:String属性,在协议TextModel中定义)。该服务拥有一个存储库,用于查找并返回符合TextModel的具体类型的模型。存储库需要保留内部工作的具体类型信息。我想让服务不受模型的具体类型的影响,这样我就不必对每个模型类型重复它。编译器不允许我这么做 问题: 我在操场上简化的以下代码将不会编译: enum Result<T> { case success(T) c
text:String
属性,在协议TextModel
中定义)。该服务拥有一个存储库,用于查找并返回符合TextModel
的具体类型的模型。存储库需要保留内部工作的具体类型信息。我想让服务不受模型的具体类型的影响,这样我就不必对每个模型类型重复它。编译器不允许我这么做
问题:
我在操场上简化的以下代码将不会编译:
enum Result<T> {
case success(T)
case error
}
// Model Layer
protocol TextModel {
var text: String { get }
}
struct Person: TextModel {
let text: String
}
// Service Layer
class TextModelService {
let repository: TextModelRepositoryType
init(repository: TextModelRepositoryType) {
self.repository = repository
}
func find(completion: @escaping (Result<TextModel>) -> ()) {
repository.find(completion: completion)
}
}
// Repository Layer
protocol TextModelRepositoryType {
func find(completion: @escaping (Result<TextModel>) -> ())
}
protocol PersonRepositoryType {
func findPerson(completion: @escaping (Result<Person>) -> ())
}
class PersonRepository: PersonRepositoryType, TextModelRepositoryType {
func find(completion: @escaping (Result<TextModel>) -> ()) {
// ERROR HERE: "Cannot convert value of type '(Result<TextModel>) -> ()' to expected argument type '(Result<Person>) -> ()'"
findPerson(completion: completion)
}
func findPerson(completion: @escaping (Result<Person>) -> ()) {
let person = Person(text: "Adam")
completion(.success(person))
}
}
let repository = PersonRepository()
let service = TextModelService(repository: repository)
service.find { result in
// result should be a Result<Person>
}
枚举结果{
成功案例(T)
案例错误
}
//模型层
协议文本模型{
变量文本:字符串{get}
}
结构人:TextModel{
让文本:字符串
}
//服务层
类TextModelService{
let存储库:TextModelRepositoryType
init(存储库:TextModelRepositoryType){
self.repository=存储库
}
func find(完成:@escaping(Result)->()){
查找(完成:完成)
}
}
//存储库层
协议TextModelRepositoryType{
func find(完成:@escaping(Result)->())
}
协议PersonRepositoryType{
func findPerson(完成:@escaping(Result)->())
}
类PersonRepository:PersonRepositoryType、TextModelRepositoryType{
func find(完成:@escaping(Result)->()){
//此处出现错误:“无法将类型为“(结果)->()”的值转换为预期的参数类型“(结果)->()”
findPerson(完成:完成)
}
func findPerson(完成:@escaping(Result)->()){
让人=人(文本:“亚当”)
完成(.success(个人))
}
}
let repository=PersonRepository()
let service=TextModelService(存储库:repository)
service.find{结果在
//结果应该是结果
}
我不明白为什么当Person
明确符合TextModel
时,编译器声明它无法将类型为“(结果)->()”的值转换为预期的参数类型“(结果)->()”
同样有趣的是,当我删除结果
类型并在完成时传递一个未包装的类型(例如(TextModel?)->()
)时,编译器不会感到不安
我是否在Swift编译器中遇到了限制?还是我遗漏了什么 因为Swift具有不变的泛型类型,
T
无法转换为T
,即使A
可以转换为B
这种情况下的一个解决方法是自己创建转换方法:
enum Result<T> {
case success(T)
case error
func cast<R>() -> Result<R>? {
switch self {
case .error: return .error
case .success(let t) where t is R: return .success(t as! R)
default: return nil
}
}
}
extension Result where T : TextModel {
func convertToTextModel() -> Result<TextModel> {
switch self {
case .error: return .error
case .success(let t): return .success(t)
}
}
}
在呼叫端:
let repository = PersonRepository()
let service = TextModelService(repository: repository)
service.find { result in
if let person: Result<Person> = result.cast() {
// ...
}
}
let repository=PersonRepository()
let service=TextModelService(存储库:repository)
service.find{结果在
如果让人:Result=Result.cast(){
// ...
}
}
是否必须使用结果
。Result
也能正常工作吗?对“swift类型差异”进行了一些搜索。斯威夫特的泛型是不变性的,也就是说,是的,这就是它的行为。斯威普,我从问题中去掉了可选性。感谢瑞奇,我忽略了结果将泛型添加到等式中的事实。谢谢你的引导。我会做些调查的。非常感谢。这是一种享受。我认为我在这里真正学到的是,我过度设计了系统,支持可测试性!再次感谢。
let repository = PersonRepository()
let service = TextModelService(repository: repository)
service.find { result in
if let person: Result<Person> = result.cast() {
// ...
}
}