使用类型擦除在 Swift 函数中返回通用类型(无法转换类型的返回表达式...)

2023-12-02

我对 swift 中的泛型有疑问。让我们公开我的代码。


protocol FooProtocol {
    associatedtype T
}

protocol Fooable { }
extension Int : Fooable { }
extension String: Fooable { }

class AnyFoo<T>: FooProtocol {
    init<P: FooProtocol>(p: P) where P.T == T { }
}

class FooIntImpClass: FooProtocol {
    typealias T = Int
}

class FooStringImpClass: FooProtocol {
    typealias T = String
}

func createOne(isInt: Bool) -> AnyFoo<Fooable> {
    if isInt {
        let anyFoo = AnyFoo(p: FooIntImpClass())
          return anyFoo
    } else {
        let anyFoo = AnyFoo(p: FooStringImpClass())
        return anyFoo
    }
}

func createTwo<F: Fooable>(isInt: Bool) -> AnyFoo<F> {
    if isInt {
        let anyFoo = AnyFoo(p: FooIntImpClass())
          return anyFoo
    } else {
        let anyFoo = AnyFoo(p: FooStringImpClass())
        return anyFoo
    }
}

createOne出现错误

无法将类型“AnyFoo”(又名“AnyFoo”)的返回表达式转换为返回类型“AnyFoo”

createTwo出现错误

无法将类型“AnyFoo”(又名“AnyFoo”)的返回表达式转换为返回类型“AnyFoo”

为什么会出现这种情况。我正在返回正确的值。

和有什么区别createOne and createTwo


编辑以回应对问题的编辑:

createTwo不起作用,因为你和我在原来的答案中所说的有同样的误解。createTwo自己决定F应该是String or Int,而不是“任何符合Fooable".

For createOne,你还有另一个常见的误解。泛型类是不变的. AnyFoo<String>不是一种AnyFoo<Fooable>。事实上,它们是完全不相关的类型!看here更多细节。

基本上,您尝试做的事情违反了类型安全,因此您重新设计 API 并选择另一种不同的方法。


原始答案(用于问题的初步修改)

您似乎对泛型有一个常见的误解。通用参数由调用者决定,而不是被调用者决定。

In createOne,你正在返回anyFoo,其类型为AnyFoo<Int>, not AnyFoo<P>。该方法(被调用者)自行决定P应该Int。这不应该发生,因为caller决定通用参数应该是什么。如果被调用者是通用的,它必须能够使用any类型(在限制范围内)。反正,P不可能Int无论如何,从那时起P: FooProtocol.

Your createOne方法根本不应该是通用的,因为它只适用于Int:

func createOne() -> AnyFoo<Int> {
    let anyFoo = AnyFoo(p: FooImpClass())
    return anyFoo
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用类型擦除在 Swift 函数中返回通用类型(无法转换类型的返回表达式...) 的相关文章

随机推荐

  • Eclipse - 导入您自己的库

    好的 希望这既快速又简单 我有两个独立的java项目 Library 和 Project 并且 Project 中有一个类想要实现 Library 中找到的方法 我正在寻找某种在 项目 类顶部进行的 导入 调用 以使 库 中找到的方法可以在
  • 更改 TextBlock 的绑定文本内子字符串的颜色

    我正在将一些财产绑定到我的TextBlock
  • 无法加载文件或程序集“MySql.Data,版本=6.3.6.0”

    我完全不知所措 我遇到了超级奇怪的问题 我仍然不明白 我正在运行 Entity Framework 4 1 MySql 5 xx 我的 MySql Connector 是 v 6 4 4 一切正常本地精美 但是每当我上传到服务器时 我都会收
  • Android MultiChoiceModeListener 支持 2.3

    为了支持操作栏 我使用 Android 支持库包 V4 和 V7 我在我的应用程序中使用 MultiChoiceModeListener 我如何将 MultiChoiceModeListener 用于 2 3 设备 工作示例 V7 impo
  • SPOJ - 运行时错误 SIGSEGV

    以下是实施中缀到后缀转换 它在我的计算机上运行良好 但当我在 SPOJ 上提交时 它给了我运行时错误 SIGSEGV 我是竞争性编程的新手 我无法处理此类错误 include
  • 使用批处理脚本读取每 5 行

    我想制作一个批处理程序 它将显示文本文件的每 5 行 例如第 1 6 11 16 行 我尝试修改此处找到的 head bat 代码 用于从文本文件读取第一行的 Windows 批处理命令 我的代码如下 echo off setlocal e
  • 避免传递 null 作为视图根(需要解析膨胀布局的根元素上的布局参数)

    为 root studio 传递 null 会给我这个警告 避免传递 null 作为视图根 需要解析膨胀布局的根元素上的布局参数 它显示空值getGroupView 请帮忙 public class ExpandableListAdapte
  • PHP群发邮件

    我在一家小型营销公司工作 该公司要求我开发一个 PHP 应用程序 以便为他们的公司发送电子邮件 而不会被列入黑名单或电子邮件显示为垃圾邮件 我对 PHP OOP 有相当好的了解 但我不明白如何构建这个程序 他们每月需要发送大约 500 00
  • 在 SimpleITK 中对 3D 图像切片进行操作并创建新的 3D 图像

    我将 3D 图像从 NIfTI 文件读入 SimpleITK 使用 python 获取每个轴向切片 对其进行处理 然后将新的 2D 切片重新插入具有 希望 适当尺寸的 3D 体积中 例如 output sitk Image original
  • 更改表文件组的有效方法

    我有大约 300 个表 它们位于不同的分区 现在这些表不再用于存储如此庞大的数据 现在 我时不时地遇到空间问题 其中一些但有价值的空间被为这些表创建的 150 个文件组占用 因此我想将表的文件组更改为任何一个而不是 150 FG 并通过删除
  • Mysql如何连接表[关闭]

    Closed 这个问题需要调试细节 目前不接受答案 我有三张桌子 表 1 包含一个主键 表 2 包含与表 1 的主键相同的外键 表 3 包含与表 2 的主键相同的外键 问题 是否可以在只知道表1的主键的情况下从表2和表3中选择信息 如果是这
  • SQL Server 2008 - 如果不存在则插入其他更新

    我很抱歉 但这是一个由两部分组成的问题 我对 SQL 非常陌生 正在尝试为我工作的小型办公室开发一个时钟应用程序 我现在正在使用 SQL 后端 并且有一个关于复合语句的问题 我遇到的问题是 如果用户尝试下班休息但从未在轮班开始时签到 SQL
  • PowerPoint 中所有幻灯片的叠加项目

    我想制作一个 PowerPoint 插件来在每张幻灯片上显示一些小的 html css 组件 而不是每次添加新幻灯片时都添加插件 我应该寻找什么 可以通过一些 Office 加载项和命令 API 来完成吗 在 PowerPoint 中 添加
  • 文件写入器覆盖先前写入的 Java

    try File file new File filePath usedcommands txt if file exists file createNewFile FileWriter fw new FileWriter file get
  • GCC 位向前扫描以查找下一个设置位?

    我有一个uint64 t我想找到第一个设置位的索引 将其重置为零并找到下一个设置位 我如何知道何时终止 全零的 BSF 未定义 const uint64 t input source if 0 input int32 t setIndex
  • Spark Scala 2.10 元组限制

    我有 66 列的 DataFrame 需要处理 几乎每个列值都需要以某种方式更改 所以我正在运行以下语句 val result data map row gt modify row getString row fieldIndex XX 直
  • 如何使用 NFC 重定向或打开我的渐进式 Web 应用程序?

    我有一个渐进式网络应用程序 app example com在 Android 上使用 Chrome 的 添加到主屏幕 按钮创建 我有一个通常会打开的 NFC 标签app example com nfc app在 Chrome 中 当点击它时
  • 如何从此结果集创建一个数组(使用遍历模型存储在数据库中的嵌套类别)?

    基于这个问题 将修改后的先序树遍历模型 嵌套集 放入 中 下面的逻辑用于构建有序列表 但是如何对数组执行相同的操作 我想构建一个嵌套数组 bootstrap loop result currDepth 1 1 to get the oute
  • 使用不透明访问令牌是否会使我的服务器有状态?

    我试图在身份验证的背景下理解 Restful API 中的无状态性 这是场景 用户登录 服务器验证用户名和密码 并生成不透明的访问令牌 它缓存与此令牌相关的一些信息 例如 过期时间 userId 此令牌在过期之前是否已显式失效等 令牌被发送
  • 使用类型擦除在 Swift 函数中返回通用类型(无法转换类型的返回表达式...)

    我对 swift 中的泛型有疑问 让我们公开我的代码 protocol FooProtocol associatedtype T protocol Fooable extension Int Fooable extension String