Swift键路径泛型和子类化

Swift键路径泛型和子类化,swift,generics,keypaths,Swift,Generics,Keypaths,我正在处理一个类,其中一个超类及其子类具有不同的属性,但所有类型都是相同的,在分配之前需要相同的处理。我已经提出了一个非常做作和简化的例子,说明我正在尝试如何处理关键路径,可能使用泛型,包括一个非最佳但有效的变体 类原始类{ //这将只允许存在于基础“OriginalClass”上的属性(这是有意义的) func updateProperty(到值:Int,键路径:ReferenceWritableKeyPath){ //有很多习惯,但有共同的逻辑 self[keyPath:keyPath]=值

我正在处理一个类,其中一个超类及其子类具有不同的属性,但所有类型都是相同的,在分配之前需要相同的处理。我已经提出了一个非常做作和简化的例子,说明我正在尝试如何处理关键路径,可能使用泛型,包括一个非最佳但有效的变体

类原始类{
//这将只允许存在于基础“OriginalClass”上的属性(这是有意义的)
func updateProperty(到值:Int,键路径:ReferenceWritableKeyPath){
//有很多习惯,但有共同的逻辑
self[keyPath:keyPath]=值
}
//这个*很有效*,但我不喜欢第一行的演员阵容,而且呼叫站点需要明确的
//关键路径(包括类型)
func updatePropertyTwo(to值:Int,keyPath:ReferenceWritableKeyPath){
guard let self=self as?GenClass else{return}
self[keyPath:keyPath]=值
}
//理想情况下,我想做这样的事情。基本上,编译器应该(也就是我希望它)能够知道这一点
//我正在开发OriginalClass的一个子类,并提供该子类除这些之外可用的关键路径
//在基础上,是超类。
//func idealNonworking(to值:Int,keyPath:ReferenceWritableKeyPath){
////有很多自定义的,但逻辑是通用的
//self[keyPath:keyPath]=值
//  }
//这抱怨说“同一类型要求使泛型参数“GenClass”非泛型”,但如果是这样的话,那也可以
//work它应该包括子类属性(但要清楚,它没有)
//func alternativeIdealYetNonworking(to value:Int,keyPath:referencewriteablekeypath),其中GenClass==Self{
////有很多自定义的,但逻辑是通用的
//self[keyPath:keyPath]=值
//  }
}
第二类:原始类{
var子类值=0
func非工作示例(){
//UpdateProperty(到:Subclass值+1,键路径:\.Subclass值)
}
func次优化工作示例(){
UpdatePropertyTwo(到:Subclass值+1,键路径:\SecondClass.Subclass值)
//UpdatePropertyTwo(to:subclass值+1,keyPath:\Self.subclass值)//运行时出错
//UpdatePropertyTwo(到:subclass值+1,键路径:\.subclass值)
}
//func OptimizeYetNonWorkingExample(){
//理想不工作(到子类值+1,键路径:\.子类值)
//  }
}
let test=SecondClass()
打印(测试子类值)
test.subOptimalWorkingExample()
打印(测试子类值)
现在,我知道为什么第一个不起作用(键路径类型由
OriginalClass
上可用的属性定义),但我不确定为什么最后一个不起作用。当然,如果有人知道如何做到这一点,那么这就没有协议扩展中允许的Self

那么重要了,所以我只写了:

protocol P {
    // put whatever methods and properties from OriginalClass the "lots of custom,
    // but common logic" need here...
}
class OriginalClass : P {}

extension P {
    func updateAProperty(to value: Int, keyPath: ReferenceWritableKeyPath<Self, Int>) {
      // lots of custom, but common logic
        self[keyPath: keyPath] = value
    }
}

这管用!问题是我必须将协议应用于所有子类,否则会出现以下错误:
protocol'VMProgregatupDating'requirement'updateProminentArtifact(with:type:keyPath:)”不能由非最终类('ApiViewModel')满足,因为它在非参数中使用了“Self”,非结果类型职位
@mredig我想你可能有一些额外的要求,你没有告诉我,或者你没有正确地应用我的答案,因为我答案中的代码不会产生任何错误。请注意,您应该将
updateProperty
作为协议扩展中的成员,而不是协议中的成员。这就解决了它!我按照协议的要求使用了这些方法。即使没有这些,它也比原来的要干净得多。
class SecondClass: OriginalClass {
    var subclassValue = 0

    func workingExample() {
      updateAProperty(to: subclassValue + 1, keyPath: \.subclassValue)
    }
}

let test = SecondClass()
print(test.subclassValue)
test.workingExample()
print(test.subclassValue)