将泛型类型传递给具有泛型约束的函数
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("")
我有一个关联类型的协议
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("")