代码之家  ›  专栏  ›  技术社区  ›  Nick

将enum映射到KeyPath以通用方式访问属性

  •  0
  • Nick  · 技术社区  · 4 年前

    我正在尝试将枚举值映射到结构上的属性,这样可以通过枚举访问这些属性,并且可以以通用的方式迭代和处理这些属性。下面是一个精心设计的例子,它演示了我遇到的编译器错误:

    import UIKit
    
    protocol AProtocol: Equatable {
        var someInstanceProperty: String { get }
    }
    
    extension Bool: AProtocol {
        var someInstanceProperty: String { "Bool" }
    }
    extension Int: AProtocol {
        var someInstanceProperty: String { "Int" }
    }
    extension String: AProtocol {
        var someInstanceProperty: String { "String" }
    }
    
    struct Values {
        var someBool = false
        var someInt = 0
        var someString = "hello"
        
        enum Properties {
            case someB, someI, someS
        }
        
        let map1: [Properties: PartialKeyPath<Values>] = [
            .someB: \Values.someBool,
            .someI: \Values.someInt,
            .someS: \Values.someString,
        ]
        
        let map2: [Properties: KeyPath<Values, AProtocol>] = [
            .someB: \Values.someBool, // Cannot convert value of type 'KeyPath<Values, Bool>' to expected dictionary value type 'KeyPath<Values, AProtocol>'
            .someI: \Values.someInt, // Cannot convert value of type 'KeyPath<Values, Int>' to expected dictionary value type 'KeyPath<Values, AProtocol>'
            .someS: \Values.someString, // Cannot convert value of type 'KeyPath<Values, String>' to expected dictionary value type 'KeyPath<Values, AProtocol>'
        ]
        
        func performSomeAction<T: AProtocol>(key: Properties, keyPath: KeyPath<Values, T>) {
            print("key \(key), value \(self[keyPath: keyPath].someInstanceProperty)")
        }
        
        func getAll1() {
            for (key, keyPath) in map1 {
                performSomeAction(key: key, keyPath: keyPath) // Cannot convert value of type 'PartialKeyPath<Values>' to expected argument type 'KeyPath<Values, T>'
            }
        }
        
        func getAll2() {
            for (key, keyPath) in map1 {
                print("key \(key), value \(self[keyPath: keyPath].someInstanceProperty)") // Value of type 'Any?' has no member 'someInstanceProperty'
            }
        }
        
        func getAll3() {
            for (key, keyPath) in map1 {
                print("key \(key), value \((self[keyPath: keyPath] as! AProtocol).someInstanceProperty)") // Protocol 'AProtocol' can only be used as a generic constraint because it has Self or associated type requirements
            }
        }
    }
    

    在里面 map1 ,值类型为 PartialKeyPath .我不能用 KeyPath 因为值类型不同(即使它们都符合 AProtocol ),所以我得到了一个编译器错误(请参阅 map2 )。的问题 map1 值会丢失其类型信息。三人 getAll 函数展示了我试图克服的各种方法,但都没有成功。我最接近的是 getAll3 ,如果我删除 Equatable 一致性来自 A协议 。不幸的是,我需要这些值在我的真实代码中是相等的。我正在将以前存储的值与当前属性值进行比较。这可能吗?

    0 回复  |  直到 4 年前
    推荐文章