热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

SwiftGenerics:无法将类型的值转换为预期的参数类型

如何解决《SwiftGenerics:无法将类型的值转换为预期的参数类型》经验,为你挑选了1个好方法。

这是我的代码:

protocol SomeProtocol {
}

class A: SomeProtocol {
}

func f1(ofType: T.Type, listener: (T?) -> Void) {
}

func f2(ofType: T.Type, listener: ([T]?) -> Void) {
}

func g() {
    let l1: (SomeProtocol?) -> Void = ...
    let l2: ([SomeProtocol]?) -> Void = ...
    f1(ofType: A.self, listener: l1) // NO ERROR
    f2(ofType: A.self, listener: l2) // COMPILE ERROR: Cannot convert value of type '([SomeProtocol]?) -> Void' to expected argument type '([_]?) -> Void'
}

第二个闭包有一个泛型类型对象数组的参数有什么问题?



1> Hamish..:

Swift 4.1更新

这是一个在此pull请求中修复的错误,它将使其成为Swift 4.1的发行版.您的代码现在可以在4.1快照中按预期编译.


Pre Swift 4.1

这看起来就像你只是将编译器拉得太远了.

它可以处理从子类型元素的数组超类型元素,例如数组转换[A][SomeProtocol]-这是协方差.值得注意的是,数组在这里始终是一个边缘情况,因为任意泛型是不变的.某些集合,例如Array,只是从编译器获得特殊处理,允许协方差.

它可以处理超类型的函数的参数与子类型的参数,例如功能转换(SomeProtocol) -> Void(A) -> Void-这是逆变.

然而,似乎它目前不能一气呵成(但实际上它应该能够;随意提交错误).

对于它的价值,这与泛型无关,以下再现了相同的行为:

protocol SomeProtocol {}
class A : SomeProtocol {}

func f1(listener: (A) -> Void) {}
func f2(listener: ([A]) -> Void) {}
func f3(listener: () -> [SomeProtocol]) {}

func g() {

    let l1: (SomeProtocol) -> Void = { _ in }        
    f1(listener: l1) // NO ERROR

    let l2: ([SomeProtocol]) -> Void = { _ in }
    f2(listener: l2) 
    // COMPILER ERROR: Cannot convert value of type '([SomeProtocol]) -> Void' to
    // expected argument type '([A]) -> Void'

    // it's the same story for function return types
    let l3: () -> [A] = { [] }
    f3(listener: l3)
    // COMPILER ERROR: Cannot convert value of type '() -> [A]' to
    // expected argument type '() -> [SomeProtocol]'
}

在修复之前,在这种情况下,一种解决方案是简单地使用闭包表达式作为两种函数类型之间的蹦床:

// converting a ([SomeProtocol]) -> Void to a ([A]) -> Void.
// compiler infers closure expression to be of type ([A]) -> Void, and in the
// implementation, $0 gets implicitly converted from [A] to [SomeProtocol].
f2(listener: { l2($0) })

// converting a () -> [A] to a () -> [SomeProtocol].
// compiler infers closure expression to be of type () -> [SomeProtocol], and in the
// implementation, the result of l3 gets implicitly converted from [A] to [SomeProtocol]
f3(listener: { l3() })

并且,适用于您的代码:

f2(ofType: A.self, listener: { l2($0) })

这是有效的,因为编译器将闭包表达式推断为类型([T]?) -> Void,可以传递给它f2.在封闭件的实施方式中,编译器随后执行的一个隐式转换$0[T]?[SomeProtocol]?.

而且,正如多米尼克暗示的那样,这个蹦床也可以作为额外的重载f2:

func f2(ofType type: T.Type, listener: ([SomeProtocol]?) -> Void) {
    // pass a closure expression of type ([T]?) -> Void to the original f2, we then
    // deal with the conversion from [T]? to [SomeProtocol]? in the closure.
    // (and by "we", I mean the compiler, implicitly)
    f2(ofType: type, listener: { (arr: [T]?) in listener(arr) })
}

允许你再次将其称为f2(ofType: A.self, listener: l2).


推荐阅读
  • Python正则表达式学习记录及常用方法
    本文记录了学习Python正则表达式的过程,介绍了re模块的常用方法re.search,并解释了rawstring的作用。正则表达式是一种方便检查字符串匹配模式的工具,通过本文的学习可以掌握Python中使用正则表达式的基本方法。 ... [详细]
  • 前景:当UI一个查询条件为多项选择,或录入多个条件的时候,比如查询所有名称里面包含以下动态条件,需要模糊查询里面每一项时比如是这样一个数组条件:newstring[]{兴业银行, ... [详细]
  • IjustinheritedsomewebpageswhichusesMooTools.IneverusedMooTools.NowIneedtoaddsomef ... [详细]
  • JDK源码学习之HashTable(附带面试题)的学习笔记
    本文介绍了JDK源码学习之HashTable(附带面试题)的学习笔记,包括HashTable的定义、数据类型、与HashMap的关系和区别。文章提供了干货,并附带了其他相关主题的学习笔记。 ... [详细]
  • 使用nodejs爬取b站番剧数据,计算最佳追番推荐
    本文介绍了如何使用nodejs爬取b站番剧数据,并通过计算得出最佳追番推荐。通过调用相关接口获取番剧数据和评分数据,以及使用相应的算法进行计算。该方法可以帮助用户找到适合自己的番剧进行观看。 ... [详细]
  • PHP图片截取方法及应用实例
    本文介绍了使用PHP动态切割JPEG图片的方法,并提供了应用实例,包括截取视频图、提取文章内容中的图片地址、裁切图片等问题。详细介绍了相关的PHP函数和参数的使用,以及图片切割的具体步骤。同时,还提供了一些注意事项和优化建议。通过本文的学习,读者可以掌握PHP图片截取的技巧,实现自己的需求。 ... [详细]
  • Commit1ced2a7433ea8937a1b260ea65d708f32ca7c95eintroduceda+Clonetraitboundtom ... [详细]
  • 目录实现效果:实现环境实现方法一:基本思路主要代码JavaScript代码总结方法二主要代码总结方法三基本思路主要代码JavaScriptHTML总结实 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • Android JSON基础,音视频开发进阶指南目录
    Array里面的对象数据是有序的,json字符串最外层是方括号的,方括号:[]解析jsonArray代码try{json字符串最外层是 ... [详细]
  • MyBatis多表查询与动态SQL使用
    本文介绍了MyBatis多表查询与动态SQL的使用方法,包括一对一查询和一对多查询。同时还介绍了动态SQL的使用,包括if标签、trim标签、where标签、set标签和foreach标签的用法。文章还提供了相关的配置信息和示例代码。 ... [详细]
  • 本文介绍了如何使用Express App提供静态文件,同时提到了一些不需要使用的文件,如package.json和/.ssh/known_hosts,并解释了为什么app.get('*')无法捕获所有请求以及为什么app.use(express.static(__dirname))可能会提供不需要的文件。 ... [详细]
  • 先看官方文档TheJavaTutorialshavebeenwrittenforJDK8.Examplesandpracticesdescribedinthispagedontta ... [详细]
  • express工程中的json调用方法
    本文介绍了在express工程中如何调用json数据,包括建立app.js文件、创建数据接口以及获取全部数据和typeid为1的数据的方法。 ... [详细]
  • Ihaveaworkfolderdirectory.我有一个工作文件夹目录。holderDir.glob(*)>holder[ProjectOne, ... [详细]
author-avatar
blue暗紫天堂
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有