具有约束关联类型错误的Swift协议“类型不可转换”
发布时间:2020-12-14 02:23:42 所属栏目:百科 来源:网络整理
导读:我创建了2个具有相关类型的协议.符合Reader的类型应该能够生成符合Value的类型的实例. 复杂层来自符合Manager的类型,应该能够生成一个具体的Reader实例,它生成一个特定类型的Value(Value1或Value2). 通过我对Manager1的具体实现,我希望它始终生成Reader1,而R
我创建了2个具有相关类型的协议.符合Reader的类型应该能够生成符合Value的类型的实例.
复杂层来自符合Manager的类型,应该能够生成一个具体的Reader实例,它生成一个特定类型的Value(Value1或Value2). 通过我对Manager1的具体实现,我希望它始终生成Reader1,而Reader1又生成Value1的实例. 有人可以解释原因
当错误的行改为(现在)返回nil时,所有编译都很好,但现在我无法实例化Reader1或Reader2. 可以将以下内容粘贴到Playground中以查看错误: import Foundation protocol Value { var value: Int { get } } protocol Reader { typealias ReaderValueType: Value func value() -> ReaderValueType } protocol Manager { typealias ManagerValueType: Value func read<ManagerReaderType: Reader where ManagerReaderType.ReaderValueType == ManagerValueType>() -> ManagerReaderType? } struct Value1: Value { let value: Int = 1 } struct Value2: Value { let value: Int = 2 } struct Reader1: Reader { func value() -> Value1 { return Value1() } } struct Reader2: Reader { func value() -> Value2 { return Value2() } } class Manager1: Manager { typealias ManagerValueType = Value1 let v = ManagerValueType() func read<ManagerReaderType: Reader where ManagerReaderType.ReaderValueType == ManagerValueType>() -> ManagerReaderType? { return Reader1()// Error: "Reader1 is not convertible to ManagedReaderType?" Try swapping to return nil which does compile. } } let manager = Manager1() let v = manager.v.value let a: Reader1? = manager.read() a.dynamicType
发生此错误是因为read函数中的ManagerReaderType只是符合Reader且其ReaderValueType等于ManagerReaderType的任何类型的通用占位符.因此,ManagerReaderType的实际类型不是由函数本身决定的,而是被赋值的变量的类型声明了类型:
let manager = Manager1() let reader1: Reader1? = manager.read() // ManagerReaderType is of type Reader1 let reader2: Reader2? = manager.read() // ManagerReaderType is of type Reader2 如果你返回nil它可以转换为任何可选类型,所以它总是有效. 作为替代方案,您可以返回特定类型的Reader类型: protocol Manager { // this is similar to the Generator of a SequenceType which has the Element type // but it constraints the ManagerReaderType to one specific Reader typealias ManagerReaderType: Reader func read() -> ManagerReaderType? } class Manager1: Manager { func read() -> Reader1? { return Reader1() } } 由于缺少“真正的”泛型,这是使用协议的最佳方法(不支持以下内容): // this would perfectly match your requirements protocol Reader<T: Value> { fun value() -> T } protocol Manager<T: Value> { func read() -> Reader<T>? } class Manager1: Manager<Value1> { func read() -> Reader<Value1>? { return Reader1() } } 所以最好的解决方法是使Reader成为泛型类,Reader1和Reader2子类是它的特定泛型类型: class Reader<T: Value> { func value() -> T { // or provide a dummy value fatalError("implement me") } } // a small change in the function signature protocol Manager { typealias ManagerValueType: Value func read() -> Reader<ManagerValueType>? } class Reader1: Reader<Value1> { override func value() -> Value1 { return Value1() } } class Reader2: Reader<Value2> { override func value() -> Value2 { return Value2() } } class Manager1: Manager { typealias ManagerValueType = Value1 func read() -> Reader<ManagerValueType>? { return Reader1() } } let manager = Manager1() // you have to cast it,otherwise it is of type Reader<Value1> let a: Reader1? = manager.read() as! Reader1? 此实现应该可以解决您的问题,但读者现在是引用类型,应该考虑复制函数. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |