Swift   发布时间:2022-03-31  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了具有约束关联类型错误的Swift协议“类型不可转换”大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。

概述

我创建了2个具有相关类型的协议.符合Reader的类型应该能够生成符合Value的类型的实例. 复杂层来自符合Manager的类型,应该能够生成一个具体的Reader实例,它生成一个特定类型的Value(Value1或Value2). 通过我对Manager1的具体实现,我希望它始终生成Reader1,而Reader1又生成Value1的实例. 有人可以解释原因 “Reader1 is not c
我创建了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?

此实现应该可以解决您的问题,但读者现在是引用类型,应该虑复制函数.

大佬总结

以上是大佬教程为你收集整理的具有约束关联类型错误的Swift协议“类型不可转换”全部内容,希望文章能够帮你解决具有约束关联类型错误的Swift协议“类型不可转换”所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。