[英]Generics and Constraints (`Instance method '…' requires that 'T' conform to 'Decodable'`)
I have a generic struct allowing different types to be used.我有一个通用结构,允许使用不同的类型。 I do not want to constrain the whole struct to only Decodable items.我不想将整个结构限制为仅可解码项目。
What is the best way to fix the following error, where I try to only execute some code if T conforms to Decodable: Instance method '...' requires that 'T' conform to 'Decodable'
修复以下错误的最佳方法是什么,我尝试仅在 T 符合 Decodable 时执行一些代码: Instance method '...' requires that 'T' conform to 'Decodable'
struct Something<T> {
...
func item<T>(from data: Data) -> T? where T: Decodable {
try? JSONDecoder().decode(T.self, from: data)
}
func getter() -> T {
let value = ...
if let value = value as? T { return value } // something simple like string
if let data = value as? Data, T.self is Decodable { // something complex
return item(from: data) ?? defaultValue // error is thrown here
}
return defaultValue
}
}
As you can see I'm checking the conformance with the if-clause, but that isn't enough to access the constrained method?如您所见,我正在检查是否符合 if 子句,但这还不足以访问受约束的方法吗? :/ :/
It makes no sense to me that T only needs to conform to Decodable
in some part but not others.对我来说,T 只需要在某些部分符合Decodable
而不是其他部分,这对我来说毫无意义。 I would rewrite the struct as我会将结构重写为
struct Something<T: Decodable> {
func item(from data: Data) -> T? {
try? JSONDecoder().decode(T.self, from: data)
}
func getter() -> T {
let value = ...
if let data = value as? Data
return item(from: data) ?? defaultvalue
}
return defaultvalue
}
}
First of all you should constrain T to Decodable when you define the struct.首先,您应该在定义结构时将 T 限制为 Decodable 。 Second, you must not define T as a generic parameter of the functions internally as it will not be treated as the same T the struct conforms to by the compiler.其次,您不能在内部将 T 定义为函数的通用参数,因为它不会被编译器视为结构符合的相同 T。 Instead it will be treated as a new and different generic type constraint (that you just happened to give the same name).相反,它将被视为一个新的和不同的泛型类型约束(您只是碰巧给出了相同的名称)。 Doing it like this is enough:这样做就足够了:
struct Something<T: Decodable> {
var defaultValue: T
var data: Data
func item(from data: Data) -> T? {
try? JSONDecoder().decode(T.self, from: data)
}
func getter() -> T {
item(from: data) ?? defaultValue
}
}
You can use an extension to define the more constrained method:您可以使用扩展来定义更受约束的方法:
struct Something<T> {
var defaultValue: T
func getter() -> T {
return defaultValue
}
}
extension Something where T: Decodable {
func getter() -> T {
// I'm assuming here that you have a property data: Data
try? JSONDecoder().decode(T.self, from: data) ?? defaultValue
}
}
It's not entirely clear how you're going to use this type in a meaningful way.目前还不完全清楚您将如何以有意义的方式使用这种类型。 The way your code is constructed, value
is Any
type.您的代码的构造方式, value
是Any
类型。 Is this what you meant?这是你的意思吗? (I'm guessing, not) (我猜,不是)
Somewhere, you'd need to make a concrete version of Something
- ie it would be Something<Int>
or Something<String>
or Something<SomeDecodableType>
- at that point T
will be that concrete type, and as you can see, there's nothing common between the various versions of T
, except Any
.在某个地方,您需要制作Something
的具体版本——即它会是Something<Int>
或Something<String>
或Something<SomeDecodableType>
——此时T
将是那个具体的类型,正如你所看到的,有T
的各种版本之间没有任何共同点,除了Any
。
So figure out what parts of Something
truly are common.所以弄清楚Something
的哪些部分真正是共同的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.