简体   繁体   English

Generics 和约束(`实例方法'...'要求'T'符合'Decodable'')

[英]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.您的代码的构造方式, valueAny类型。 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.

相关问题 实例方法要求“ NSObject”符合 - Instance method requires that 'NSObject' conform 实例方法“items”要求“listen”符合“sequence” - Instance method 'items' requires that 'listen' conform to 'Sequence' 实例方法“包含”要求“UITextField”符合“StringProtocol” - Instance method 'contains' requires that 'UITextField' conform to 'StringProtocol' 错误:实例方法 'onReceive(_:perform:)' 要求 'Int' 符合 'Publisher' - Error: Instance method 'onReceive(_:perform:)' requires that 'Int' conform to 'Publisher' 实例方法 'items(cellIdentifier:cellType:)' 要求 'Model' 符合 'Sequence' - Instance method 'items(cellIdentifier:cellType:)' requires that 'Model' conform to 'Sequence' 实例方法 'save(_:where:completion:)' 要求 'PostModel' 符合 'Model' - Instance method 'save(_:where:completion:)' requires that 'PostModel' conform to 'Model' Codable class 不符合“可解码”协议 - Codable class doesn't conform to protocol 'Decodable' Swift 4.2:类型“ T”不符合协议“可解码” - Swift 4.2 : Type 'T' does not conform to protocol 'Decodable' 不符合协议可解码 - Does not conform to protocol Decodable Swift Array 按属性排序错误:实例方法“localizedCaseInsensitiveCompare”需要“String?” 符合 &#39;StringProtocol&#39; - Swift Array Sort by Property Error : Instance method 'localizedCaseInsensitiveCompare' requires that 'String?' conform to 'StringProtocol'
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM