swift 泛型完成作为非泛型传递

fivyi3re  于 2023-06-21  发布在  Swift
关注(0)|答案(2)|浏览(94)

我正在做一些框架,遇到了一个问题。
我有一个公共协议:

public protocol MyPublicProtocol1 {
}

和另一个,它包含一个传递了泛型参数的函数。泛型参数具有约束-参数类型必须实现第一个公共协议:

public protocol MyPublicProtocol2 {
    func someFunc<T: MyPublicProtocol1>(completion: (T) -> ())
}

那么我就不在公共课上实现我的协议。在那个带泛型参数的函数中,我必须调用另一个不带泛型参数的函数,看起来像这样:

func anotherFuncWith(completion: (MyPublicProtocol1) -> ())

下面是实现的样子:

class MyPublicProtocol1Impl: MyPublicProtocol1 {
}

class MyPublicProtocol2Impl: MyPublicProtocol2 {
    func someFunc<T: MyPublicProtocol1>(completion: (T) -> ()) {
        anotherFuncWith(completion: completion)
    }
}

当然最后一个字符串有个错误。
我不能声明 someFunc(completion:),而不是像这样的泛型参数:

func someFunc(completion: (MyPublicProtocol1Impl) -> ())

因为 * MyPublicProtocol 1 Impl * 类不能是公共的。由于某些原因,我也不能声明anotherFuncWith(completion:)接受泛型参数。
有没有一种方法可以将(T: MyPublicProtocol1) -> ()完成转换为(MyPublicProtocol1) -> ()
任何帮助或建议都非常感谢!谢谢你阅读我的故事!

ercv8c1e

ercv8c1e1#

你要求的是无法证明的事实。你有一个方法:

func anotherFuncWith(completion: (MyPublicProtocol1) -> ())

它接受一个可以接收 * any * MyPublicProtocol1的方法。然后你传递给它一个类型的方法:

(T: MyPublicProtocol1) -> ()

anotherFuncWith可能传递不是T的内容,此时这是未定义的。为了更具体,让我们去掉这里的大部分内容,使MyPublicProtocol1成为Any(只是选择一个普通的协议)。

func anotherFuncWith(completion: (Any) -> ()) {
    completion("This is a string which is an Any, so that's fine")
}

func someFunc<T: Any>(completion: (T) -> ()) {
    anotherFuncWith(completion: completion)
}

这无法完全像您的示例那样编译。现在让我们想想,如果它 * 确实 * 编译了,我可以做什么。我可以打电话:

func complete(x: Int) -> () {
    print(x + 1)
}

someFunc(completion: complete)

所以现在anotherFuncWith调用complete,传递一个不能添加的String。撞车
这里的根本问题是您已经得到了covariance and contravariance
我们怎么解决那要看你的意思了这个代码有点奇怪。你关心T的实际类型吗?你好像从来没用过。如果你不在乎,那就使用协议:

public protocol MyPublicProtocol2 {
    func someFunc(completion: (MyPublicProtocol1) -> ())
}

如果你关心实际的类型,使用PAT:

public protocol MyPublicProtocol2 {
    associatedtype T: MyPublicProtocol1
    func someFunc(completion: (T) -> ())
}

或者你可能想重新考虑一下是否需要一个协议。我经常发现人们在还不需要的时候就去找协议。您是否有这些协议的多种实现?是否有多个类型被传递?如果没有,我会简化,只有当你有一个真正的问题,你正在解决当前的代码时,才使用泛型/协议。(你可能需要它们;这只是我的股票建议,许多人发现当他们过度设计时很有用。

jc3wubiy

jc3wubiy2#

绕过这件事的卑鄙方法是

func someFunc<T: MyPublicProtocol1>(completion: (T) -> ()) {
    anotherFuncWith { (thing) in
        if let tThing = thing as? T {
            completion(tThing)
        }
    }
}

我只会这样做,如果你是 * 非常 * 肯定的代码围绕它,因为它肯定是易错的。
还有,这个也行。我不确定你实际上想做什么,所以我不确定它是否能解决你的问题

func anotherFuncWith<T: MyPublicProtocol1>(completion: (T) -> ()) {

}

class MyPublicProtocol2Impl: MyPublicProtocol2 {

     func someFunc<T: MyPublicProtocol1>(completion: (T) -> ()) {
         anotherFuncWith(completion: completion)
    }
}

相关问题