简体   繁体   English

Swift - 协议和扩展中的 KeyPath 问题

[英]Swift - Problems with KeyPath in protocols and extension

I'm using Swift 5.7, Xcode 14.0 beta (14A5228q)我正在使用 Swift 5.7、Xcode 14.0 beta (14A5228q)

I'm trying to get an element knowing the ID (Element conforms Identifiable protocol) in an Tree Structure implementing from arrays, I mean, I had one array with Identifiable values/objects and the element has a property (see the reversePath) that is an array with object with the same kind of it self.我试图让一个元素知道从数组实现的树结构中的 ID(元素符合 Identifiable 协议),我的意思是,我有一个带有 Identifiable 值/对象的数组,并且该元素有一个属性(参见 reversePath)一个数组,其对象与它自身的类型相同。

I don't know why de following code doesn't work.我不知道为什么下面的代码不起作用。

extension Array where Element: Identifiable{
    subscript(index: Element.ID?, recursivePath: KeyPath<Element,Array<Element>>) -> Element?{
        if( index != nil){
            for e in self{
                if(e.id == index){
                    return e
                }else{
                    let array: [any Identifiable] = e[keyPath: recursivePath] as [any Identifiable]
                    let ret = array[index: index, recursivePath: recursivePath]
                    if(ret != nil){
                        return ret
                    }
                }
            }
        }
        return  nil
    }
}

It's seems that好像是这样

e[keyPath: recursivePath] as [any Identifiable]

doesn't recognise不认识

extension Array where Element: Identifiable

First, you don't need as [any Identifiable] here at all, and don't want it.首先,您根本不需要as [any Identifiable] ,也不想要它。 That would force a copy of the array to box the elements in an existential wrapper.这将强制数组的副本将元素装箱在存在包装器中。

But that's not the problem.但这不是问题。 You've just confused subscript parameters a little bit, because they don't work like function parameters.您只是稍微混淆了下标参数,因为它们不像函数参数那样工作。 Instead of the external name automatically being the internal name (like in functions), subscript parameters default to having no external name.不同于外部名称自动成为内部名称(如在函数中),下标参数默认为没有外部名称。 So:所以:

Definition:                             Called as:
------------------------------------------------------
subscript(x: Int, y: Int) -> Int        xs[x, y]
subscript(x x: Int, y y: Int) -> Int    xs[x: x, y: y]

So to work they way you've written it, you need to change your signature to (notice the duplicated parameter names):因此,要按照您编写的方式工作,您需要将签名更改为(注意重复的参数名称):

subscript(index index: Element.ID?, recursivePath recursivePath: KeyPath<Element,Array<Element>>) -> Element?{

With that, you can change the array assignment to:这样,您可以将数组分配更改为:

let array = e[keyPath: recursivePath]

And it should compile.它应该编译。 (I haven't dug into whether it will actually do what you want it to do, but it will compile.) (我还没有深入研究它是否真的会做你想做的事情,但它会编译。)

For more on subscript parameters, see Subscript Declarations in the Swift Language Reference:有关下标参数的更多信息,请参阅 Swift 语言参考中的下标声明

Subscript parameters follow the same rules as function parameters, with two exceptions.下标参数遵循与函数参数相同的规则,但有两个例外。 By default, the parameters used in subscripting don't have argument labels, unlike functions, methods, and initializers.默认情况下,下标中使用的参数没有参数标签,这与函数、方法和初始化程序不同。 However, you can provide explicit argument labels using the same syntax that functions, methods, and initializers use.但是,您可以使用与函数、方法和初始化程序相同的语法来提供显式参数标签。

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

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