gpt4 book ai didi

Swift,基于扩展协议(protocol)的类不符合原始协议(protocol)

转载 作者:行者123 更新时间:2023-11-28 09:43:21 25 4
gpt4 key购买 nike

这些协议(protocol)让我做噩梦。

我正在尝试实现一些符合它们的协议(protocol)和类,这样我就可以拥有默认实现,但可以通过扩展协议(protocol)/类来实现自定义实现。到目前为止,这就是我所拥有的:

protocol ProtA {
var aProperty: String { get set }
var anotherProperty:String { get set }

func aFunc (anArgument: String) -> String
}

protocol ProtB: ProtA {
var aThirdProperty: String { get set }
}

protocol ProtC {
func doSomething(parameter: Int, with anotherParameter: ProtA)
}

class ClassA: ProtA {
var aProperty: String = "Hello, I'm a String."
var anotherProperty: String = "I'm not the same String."

func aFunc (anArgument: String) -> String {
return anArgument
}
}

class ClassB: ProtB {

var aProperty: String = "Hello, I'm a String."
var anotherProperty: String = "I'm not the same String."
var aThirdProperty: String = "I'm yet another String!"

func aFunc (anArgument: String) -> String {
return anArgument
}
}



class ClassC: ProtC {

func doSomething(parameter: Int, with anotherParameter: ProtA) {
print (anotherParameter.aProperty) // Works fine.

}

}

如果我这样做

class ClassC: ProtC {

func doSomething(parameter: Int, with anotherParameter: ProtA) {
print (anotherParameter.aProperty) // Works fine.

}

}

但是,如果我这样做

class ClassD: ProtC {

func doSomething(parameter: Int, with anotherParameter: ProtA) {

print (anotherParameter.aThirdProperty) // Value of type 'ProtA' has no member 'aThirdProperty'

}

}

而且,如果我这样做

class ClassE: ProtC {

func doSomething(parameter: Int, with anotherParameter: ProtB) {

print (anotherParameter.aThirdProperty) // Type 'ClassE' does not conform to protocol 'ProtC'

}

}

我做错了什么?

最佳答案

问题

从类型继承时,您不能缩小重写函数中使用的参数类型。这是您通过将参数从类型 ProtA(更通用的类型)更改为 ProtB(更具体的类型)所做的。

这是 Liskov substitution principle 的结果.简而言之,子类必须能够(至少)父类(super class)可以做的所有事情。

ProtC 建立所有符合类型的函数 func doSomething(parameter: Int, with anotherParameter: ProtA),类型为 (Int, ProtA) -> 无效)

您在 ClassE 中修改的函数的类型为 (Int, ProtB) -> Void。但是,此功能不能再替代它覆盖的功能。

假设可以做您尝试过的事情。看看会发生什么:

let instanceConformingToProtA: ProtA = ClassA()

let instanceConformingToProtC: ProtC = ClassE()

// This would have to be possible:
instanceConformingToProtC(parameter: 0, amotherParameter: instanceConformingToProtA)

但是,ClassE() 不能instanceConformingToProtA 作为其第二个参数的有效参数,因为它是一个 ProtA 不是所需的 ProtB

解决方案

此问题的解决方案完全取决于您要实现的目标。在继续之前,我需要更多信息。

根据经验,在覆盖继承成员时:

  • 参数类型必须相同或更通用。
    • 例如您不能使用 Car 类型的参数覆盖函数,并将参数类型更改为 RaceCar。这样做会破坏您的类使用 RaceCar 的能力,而 LSP 必须能够做到这一点。
    • 例如您可以使用 Car 类型的参数覆盖函数,并将参数更改为 Vehicle。这样做可以保留您的类(class)使用“车辆”的能力。
  • 返回类型必须相同或更具体。
    • 例如您不能使用返回 Vehicle 的函数覆盖返回类型为 Car 的函数。这样做将意味着返回的值比父类(super class)保证的值“不那么强大”。
    • 例如您可以使用返回 RaceCar 的函数覆盖返回类型为 Car 的函数。这样做意味着返回值“更强大”,并且它至少与父类(super class)保证的一样多。

关于Swift,基于扩展协议(protocol)的类不符合原始协议(protocol),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41726491/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com