简体   繁体   English

基于Struct泛型类型调用正确的函数实现

[英]Invoking Right Function Implementation Based on Struct Generic Type

A struct with a generic type can be extended with a where clause to add new functionality when the generic type conforms to a certain protocol.具有泛型类型的struct可以使用where子句进行扩展,以where泛型类型符合特定协议时添加新功能。 What am trying to accomplish is slightly different.我试图完成的事情略有不同。 I have a struct with a generic type, and a function that I want to change its implementation if the generic type conforms to Codable .我有一个具有泛型类型的struct和一个函数,如果泛型类型符合Codable ,我想更改其实现。 Unfortunately, the overriden function in the extension never gets triggered, if I call the function from within the struct itself.不幸的是,如果我从结构本身内部调用函数,则扩展中的覆盖函数永远不会被触发。 But if I called it from outside, the right implementation is triggered.但是如果我从外部调用它,就会触发正确的实现。

struct GenericStruct<T> {

    private var _value: T

    var value: T {
        get {
            printText()
            return _value
        }
        set {
            _value = newValue
        }
    }

    init(value: T) {
        self._value = value
    }

    func printText() {
        print("General Print Function")
    }
}

extension GenericStruct where T: Codable {
    func printText() {
        print("Codable Function")
    }
}

let test = GenericStruct(value: 1)
print(test.value) // print General Print Function
test.printText() // print Codable Function

Is there a way to invoke printText() function based on T type from within the struct?有没有办法从结构内调用基于T类型的printText()函数?

EDIT:编辑:

Am trying to invoke the right implementation from inside a propertyWrapper struct我正在尝试从propertyWrapper结构内部调用正确的实现

@propertyWrapper struct Caching<Value> {

    var key: String
    var defaultValue: Value
    var cachingType = CachingType.userDefaults

    enum CachingType {
        case userDefaults
        case custom
    }

    var wrappedValue: Value {
        get {
            switch cachingType {
            case .userDefaults:
                return UserDefaults.standard.value(forKey: key) as? Value ?? defaultValue
            case .custom:
                return retrieveValueFromCachingLayer()
            }
        }
        set {
            switch cachingType {
            case .userDefaults:
                UserDefaults.standard.set(newValue, forKey: key)
            case .custom:
                store(value: newValue)
            }
        }
    }

    func store(value: Value) {
       assertionFailure("This value type is not supported by the property wrapper")
    }

    func retrieveValueFromCachingLayer() -> Value {
        assertionFailure("This value type is not supported by the property wrapper")
        return defaultValue
    }

}

extension Caching where Value: Codable {
    func retrieveValueFromCachingLayer() -> Value {
        print("retrieve value from a custom caching layer")
        return defaultValue
    }

    func store(value: Value) {
       print("store value in a custom caching layer")
    }
}

Not without redefinition.并非没有重新定义。 The cleanest way, I think, is to separate implementations in extensions, but you can also leave what you have already and just add the specialized value .我认为,最简洁的方法是将扩展中的实现分开,但您也可以保留已有的内容,只添加专门的value

struct GenericStruct<T> {
  private var _value: T

  init(value: T) {
    _value = value
  }
}

extension GenericStruct {
  var value: T {
    get {
      printText()
      return _value
    }
    set {
      _value = newValue
    }
  }

  func printText() {
    print("General Print Function")
  }
}

extension GenericStruct where T: Codable {
  var value: T {
    get {
      printText()
      return _value
    }
    set {
      _value = newValue
    }
  }

  func printText() {
    print("Codable Function")
  }
}

Edit after learning that you're trying to work with property wrappers:在了解到您正在尝试使用属性包装器后进行编辑:

@propertyWrapper struct UserDefault<Value> {
  var key: String
  var defaultValue: Value

  var wrappedValue: Value {
    get {
      UserDefaults.standard.value(forKey: key) as? Value ?? defaultValue
    }
    set {
      UserDefaults.standard.set(newValue, forKey: key)
    }
  }
}

@propertyWrapper struct Caching<Value: Codable> {
  var defaultValue: Value

  var wrappedValue: Value {
    get {
      print("retrieve value from a custom caching layer")
      return defaultValue
    }
    set {
      print("store value in a custom caching layer")
    }
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM