[英]Swift: constrain a generic parameter for use in a more constrained generic function
I'm implementing a class which needs to conform to a protocol that looks like this:我正在实现一个需要符合如下协议的类:
protocol P {
func magic<T>(_ thing: Thing, as type: T.Type) -> T
}
This protocol is provided by third-party code, which means I can't change it in any way in order to solve this problem.此协议由第三方代码提供,这意味着我无法以任何方式更改它以解决此问题。
Now, I have a generic function现在,我有一个通用函数
func magicForObject<T: AnyObject>(_ thing: Thing, as type: T.Type) -> T
and I want to call it from within my implementation of magic
, just for input thing
s which are in fact objects.我想从我的magic
实现中调用它,只是为了输入的thing
,它们实际上是对象。 That is, I want to do something like this:也就是说,我想做这样的事情:
func magic<T>(_ thing: Thing, as type: T.Type) -> T {
if T.self is AnyClass {
return magicForObject(thing, as: type)
}
else {
// do something else
}
}
but I can't find any way to make this work.但我找不到任何方法来完成这项工作。 The code above obviously doesn't compile, and neither does stuff like上面的代码显然不能编译,类似的东西也不能编译
if let T_ = T.self as? AnyClass { ... }
because T_
is just a normal variable, not a generic parameter (which is presumably compile-time).因为T_
只是一个普通变量,而不是一个通用参数(大概是编译时)。
I also tried doing this:我也试过这样做:
func magic<T: AnyObject>(_ thing: Thing, as type: T.Type) -> T { ... }
func magic<T>(_ thing: Thing, as type: T.Type) -> T { ... }
and implementing the two separately.并分别实施两者。 The constrained AnyObject
one is correctly called if calling this function directly on the object, but not when the object is cast to protocol type P
, in which case the second one is always used.如果直接在对象上调用此函数,则会正确调用受约束的AnyObject
,但在将对象AnyObject
为协议类型P
时则不会,在这种情况下,始终使用第二个。
This situation seems hopelessly constrained, but are there any workarounds I haven't thought of?这种情况似乎无可救药地受到限制,但有没有我没有想到的解决方法?
It looks like this isn't currently possible in Swift.看起来这在 Swift 中目前是不可能的。 I've made a post pitching the idea in the Swift forums;我在 Swift 论坛上发表了一篇文章来宣传这个想法; please feel free to chime in if this is something you also need.如果这也是您需要的东西,请随时加入。
Your example is kind of hard to work with, so I had to do a lot of assumptions, but I guess this should do it for what you are requiring.你的例子有点难以使用,所以我不得不做很多假设,但我想这应该满足你的要求。
From what you said you have a given protocol P:根据您所说的,您有一个给定的协议 P:
protocol P {
func magic<T>(_ thing: Thing, as type: T.Type) -> T
}
Lets give P a default implementation of what you need it to do:让我们给 P 一个你需要它做的默认实现:
extension P {
// Implementation for magic where T is a class
func magic<T>(_ thing: Thing, as type: T.Type) -> T where T: AnyObject {
print("AnyObject Called")
return Test2() as! T
}
// Implementation for magic where T is a struct
func magic<T>(_ thing: Thing, as type: T.Type) -> T {
print("Struct Called")
return Test() as! T
}
}
You have a class that will conform to P你有一个符合 P 的类
class Test2: P {
}
Lets assume you have this Thing object and a struct we want to pass to see if we have the right results:让我们假设你有这个 Thing 对象和一个我们想要传递的结构,看看我们是否有正确的结果:
class Thing {
}
struct Test {
}
Now lets test if we call magic
on Test2
if it will call the right function accordingly to what type
is passed to magic
现在让我们测试一下我们是否在Test2
上调用magic
是否会根据传递给magic
type
调用正确的函数
let test = Test()
let test2 = Test2()
// T is Test2 so its a class
test2.magic(Thing(), as: Test2.self)
// T is Test so its a struct
test2.magic(Thing(), as: Test.self)
The Print Output calls打印输出调用
AnyObject Called
Struct Called
which seems like you could do something for structs
and another thing for classes
看起来你可以为structs
做一些事情,而为classes
做另一件事
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.