将泛型类型传递给具有泛型约束的函数

Passing a generic type to a function with generic constraint

我有一个关联类型的协议

protocol ProtocolA {
  associatedType someType
}

现在我有两个通用函数

func funcA<someType>(_ data:someType) {
    funcB(data) // cannot call
}

func funcB<someType:ProtocolA>(_ data:someType) {

}

我一直在尝试从 funcA 调用 funcB,但它不起作用我收到错误

Instance method 'funcB' requires that 'someType' conform to 'ProtocolA'

现在我知道 funcA 中的通用类型符合 ProtocolA。无论如何也可以确保编译器也知道它吗?

我无法更改 funcA 方法声明以放置通用约束,因为这是另一个协议的要求。

我已经尝试通过

在 funcA 中使用 some 关键字
var obj : some ProtocolA = data

但是我收到了错误

Property declares an opaque return type, but cannot infer the underlying type from its initializer expression

简而言之,我可以在不更改 funcA 签名的情况下从 funcA 调用 funcB,但是可以将 funcB 签名更改为所需的任何内容

****编辑*****添加了更多信息

funcA 被协议调用

protocol CommonService {
    func funcA<ModelType>(_ data:ModelType)
}

class CommonServiceImpl : CommonService {
    func funcA<someType>(_ data:someType) {
        funcB(data) // cannot call
    }

    func funcB<someType:ProtocolA>(_ data:someType) {
        //SomeCode here required that someType must implement ProtocolA
    }
}

ProtocolA 包含在无法更改的第三方 pod 中。

*******编辑***********我是如何解决这个问题的

感谢@Mojtaba Hosseini 的回答,我对如何解决我的问题有了一个非常好的想法。

我只是在我的 CommonServiceProtocol 中写了一个重载函数

protocol CommonService {
    func funcA<ModelType>(_ data:ModelType)
    func funcA<ModelType>(_ data:ModelType) where ModelType:ProtocolA
}

class CommonServiceImpl : CommonService {
    func funcA<someType>(_ data:someType) {
        funcB(data) // cannot call
    }

    func funcA<someType>(_ data:someType) where ModelType:ProtocolA {
        funcB(data) // can be called
    }

    func funcB<someType:ProtocolA>(_ data:someType) {
        //SomeCode here required that someType must implement ProtocolA
    }
}

我的意思是这不是一个完美的解决方案,但考虑到在第三方 pod 中使用 ProtocolA 对 associatedType 的硬依赖,我会说它工作正常,这是尽可能避免第三方依赖的原因之一.

根据您的要求,我认为您可以将 funcB 的签名与 funcA 匹配。参考以下代码:

func funcA<someType>(_ data:someType) {
    funcB(data) 
}

func funcB<someType>(_ data:someType) {

}

如上代码所示,可以去掉funcB中someType的类型约束。

在函数 B 中只需添加一个参数,告诉编译器您期望的类型,如果您真的想确定该类型是您的协议,请添加检查:

func transform<T>( data : T ){
guard let  data = data as? Monster else {
        print("data is not a monster type")
        return
    }
intoMonster(Monster.self, data: data)
}

func intoMonster<T> (_ type : T.Type , data : T){
}

Is there any way to also make sure that the compilers know it too?

您必须为 funcA 实现重载并约束它:

func funcA<someType>(_ data: someType) {
    /* funcB(data) */ cannot call
    print("Not detected")

}

func funcA<someType>(_ data: someType) where someType: ProtocolA {
    funcB(data) // can call ✅
    print("Detected")
}

所以调用 funcA("") 将得到 Not detected 但符合协议并调用相同的函数将导致 Detected

// extension String: ProtocolA { typealias someType = String } // uncomment to see
funcA("")