返回类型为协议的泛型函数与参数和返回类型为协议的非泛型函数的区别

Posted

技术标签:

【中文标题】返回类型为协议的泛型函数与参数和返回类型为协议的非泛型函数的区别【英文标题】:Difference between generic function whose return type is protocol and nongeneric function whose argument and return type are protocol 【发布时间】:2021-05-24 02:15:04 【问题描述】:

在处理 opaque 类型时,我在 Swift 的官方文档中阅读了这一部分。

这种方法的另一个问题是形状变换 不要筑巢。翻转三角形的结果是一个类型的值 形状,protoFlip(:) 函数接受某种类型的参数 符合 Shape 协议的。但是,协议的值 类型不符合该协议;返回的值 protoFlip(:) 不符合 Shape。这意味着像这样的代码 protoFlip(protoFlip(smallTringe)) 应用多个 转换无效,因为翻转的形状不是有效的 protoFlip(_:) 的参数。

这部分让我想到了返回类型为协议的嵌套函数,我想在操场上玩一下协议返回类型。结果,我创建了一个名为 Example 的协议,以及一个符合 Example 协议的非泛型和泛型具体类型。由于关注返回类型,我保留了协议要求尽可能简单的“示例”方法实现。

protocol Example 
    func sample(text: String) -> String


struct ExampleStruct: Example 
    func sample(text: String) -> String 
        return text
    


struct ExampleGenericStruct<T: Example>: Example 
    var t: T
    func sample(text: String) -> String 
        return t.sample(text: "\n")
    

之后,我创建了一个泛型函数,该函数具有 Example 协议的参数约束并返回 Example 协议。然后,我测试了我的嵌套函数。

func genericTestExample<T: Example>(example: T) -> Example 
    return ExampleGenericStruct(t: example)


genericTestExample(example: genericTestExample(example: ExampleStruct()))

我收到了这个错误:

协议类型'Example'的值不能符合'Example';只要 struct/enum/class 类型可以符合协议

这是我所期望的。函数返回协议本身,而不是符合它的具体类型。

最后,我又写了一个函数。

func testExample(example: Example) -> Example 
    if example is ExampleStruct 
        return example
    
    return ExampleGenericStruct(t: ExampleStruct())

当我运行代码时,我可以成功嵌套这个函数。

testExample(example: testExample(example: ExampleStruct()))

只要符合 Example 协议,我就可以将任何值传递给 genericTestExample 和 testExample 函数。此外,它们具有相同的协议返回类型。我不知道为什么我可以嵌套 testExample 函数而我不能嵌套 genericTestExample 函数,反之亦然。

【问题讨论】:

testExample 接受Example 类型的参数,这也是它的返回值——这就是它在这里工作的原因。另一方面,genericTestExample 接受 T: Example 类型的参数,但返回 Example - 正如您所指出的,这是不被接受的,因为 Example 不符合 Example - @ 的要求987654332@ 【参考方案1】:

斯威夫特 5.4 2021-09-27 08:36 UTC

@ceylanburak

你应该在swift中使用不透明类型


// some Example is **Opaque Types** !!!
func genericTestExample<T: Example>(example: T) -> some Example 
    return ExampleGenericStruct(t: example)


现在跟随你以前的想法

genericTestExample(example: genericTestExample(example: ExampleStruct()))

它等于

let e1: some Example = genericTestExample(example: ExampleStruct())
genericTestExample(example: e1)

【讨论】:

以上是关于返回类型为协议的泛型函数与参数和返回类型为协议的非泛型函数的区别的主要内容,如果未能解决你的问题,请参考以下文章

是否可以在 TypeScript 中传播独特的泛型类型?

TypeScript 中具有泛型类型参数的泛型类型的替代方案

Python:输入一个接收类型并返回该类型实例的泛型函数

返回值与参数的泛型一致

匹配参数的可空性和返回类型的泛型类型参数

仅适用于数值类型的泛型类型约束