在带有Swift的函数中使用类型擦除返回通用类型(无法转换类型的返回表达式…) [英] Use Type Erasure return Generic Type in a function with Swift (Cannot convert return expression of type…)

查看:135
本文介绍了在带有Swift的函数中使用类型擦除返回通用类型(无法转换类型的返回表达式…)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我很快就遇到了泛型的问题.让我们公开我的代码.

I have a problem with generics in swift. Let's expose my code.


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"的

Cannot convert return expression of type 'AnyFoo' (aka 'AnyFoo') to return type 'AnyFoo'

createTwo出现错误

无法将类型为"AnyFoo"的返回表达式(也称为"AnyFoo")转换为类型为"AnyFoo"的

Cannot convert return expression of type 'AnyFoo' (aka 'AnyFoo') to return type 'AnyFoo'

为什么会这样.我返回的是正确的值.

Why is this happening. I'm returning the correct value.

createOnecreateTwo

推荐答案

编辑以答复对问题的

createTwo不起作用,因为您的误解与我在原始答案中所说的相同. createTwo独自决定F应该是StringInt,而不是任何符合Fooable的类型".

createTwo doesn't work because you have the same misconception as I said in my original answer. createTwo decided on its own that F should be either String or Int, rather than "any type that conforms to Fooable".

对于createOne,您还有另一个常见的误解. 通用类是不变的. AnyFoo<String>不是AnyFoo<Fooable>的一种.实际上,它们是完全无关的类型!有关更多详细信息,请参见此处.

For createOne, you have another common misconception. Generic classes are invariant. AnyFoo<String> is not a kind of AnyFoo<Fooable>. In fact, they are totally unrelated types! See here for more details.

基本上,您尝试执行的操作违反了类型安全性,因此您重新设计了API,并选择了另一种不同的方法.

Basically, what you are trying to do violates type safety, and you redesign your APIs and pick another different approach.

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

Original answer (for initial revision of question)

您似乎对泛型有一个普遍的误解. 通用参数由调用者而不是被调用者决定.

You seem to be having a common misconception of generics. Generic parameters are decided by the caller, not the callee.

createOne中,您将返回类型为AnyFoo<Int>而不是AnyFoo<P>anyFoo.方法(被调用方)已自行决定P应该为Int.这不应该发生,因为 caller 决定应该使用什么通用参数.如果被调用方是通用的,则它必须能够使用 any 类型(在约束内).无论如何,由于P: FooProtocol,所以P不能再是Int.

In createOne, you are returning anyFoo, which is of type AnyFoo<Int>, not AnyFoo<P>. The method (callee) have decided, on its own, that P should be Int. This shouldn't happen, because the caller decides what generic parameters should be. If the callee is generic, it must be able to work with any type (within constraints). Anyway, P can't be Int here anyway, since P: FooProtocol.

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

Your createOne method should not be generic at all, as it only works with Int:

func createOne() -> AnyFoo<Int> {
    let anyFoo = AnyFoo(p: FooImpClass())
    return anyFoo
}

这篇关于在带有Swift的函数中使用类型擦除返回通用类型(无法转换类型的返回表达式…)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆