Voj*_*vik 50 xcode swift swift2
我正在尝试Swift协议扩展,我发现这个令人困惑的行为.你能帮助我如何得到我想要的结果吗?
请参阅代码最后4行的注释.(如果需要,可以将其粘贴到XCode7游乐场).谢谢!!
//: Playground - noun: a place where people can play
import UIKit
protocol Color { }
extension Color { var color : String { return "Default color" } }
protocol RedColor: Color { }
extension RedColor { var color : String { return "Red color" } }
protocol PrintColor {
func getColor() -> String
}
extension PrintColor where Self: Color {
func getColor() -> String {
return color
}
}
class A: Color, PrintColor { }
class B: A, RedColor { }
let colorA = A().color // is "Default color" - OK
let colorB = B().color // is "Red color" - OK
let a = A().getColor() // is "Default color" - OK
let b = B().getColor() // is "Default color" BUT I want it to be "Red color"
Run Code Online (Sandbox Code Playgroud)
mat*_*att 49
简短的回答是协议扩展不会进行类多态.这是有道理的,因为一个协议可以被struct或enum采用,并且因为我们不希望仅仅采用协议来引入动态调度而不需要它.
因此,在实例中getColor(),color实例变量(可能更准确地写为self.color)并不意味着你认为它的作用,因为你在思考类多态而协议不是.这样可行:
let colorB = B().color // is "Red color" - OK
Run Code Online (Sandbox Code Playgroud)
...因为你要求课程解决color,但这不符合你的期望:
let b = B().getColor() // is "Default color" BUT I want it to be "Red color"
Run Code Online (Sandbox Code Playgroud)
...因为该getColor方法完全在协议扩展中定义.您可以通过重新定义getColorB 来解决问题:
class B: A, RedColor {
func getColor() -> String {
return self.color
}
}
Run Code Online (Sandbox Code Playgroud)
现在这个类getColor被称为,它具有多态的概念self.
这里有两个非常不同的问题:协议的动态行为和协议“默认”实现的解析。
在动态方面,我们可以用一个简单的例子来说明问题:
protocol Color { }
extension Color {
var color: String { return "Default color" }
}
class BlueBerry: Color {
var color: String { return "Blue color" }
}
let berry = BlueBerry()
print("\(berry.color)") // prints "Blue color", as expected
let colorfulThing: Color = BlueBerry()
print("\(colorfulThing.color)") // prints "Default color"!
Run Code Online (Sandbox Code Playgroud)
正如您在回答中指出的那样,如果您将其定义color为原始Color协议的一部分,则可以获得动态行为(即,从而指示编译器合理地期望符合标准的类实现此方法,并且仅在未找到的情况下才使用协议的实现) :
protocol Color {
var color: String { get }
}
...
let colorfulThing: Color = BlueBerry()
print("\(colorfulThing.color)") // now prints "Blue color", as expected
Run Code Online (Sandbox Code Playgroud)现在,在您的回答中,您质疑为什么当B是A.
我认为记住协议扩展中的方法实现是“默认”实现会有所帮助,即如果符合的类本身没有实现它,则使用的实现。在您的情况下,混淆的根源来自这样一个事实,即B符合RedColor的默认实现为color,但B也是A符合的子类Color,其具有不同的默认实现color。
所以,我们可能会质疑 Swift 对这种情况的处理(就我个人而言,我更愿意看到关于这种内在模棱两可的情况的警告),但在我看来,问题的根源在于有两种不同的层次结构(OOP 对象层次结构)子类和协议继承的 POP 协议层次结构),这导致了两个相互竞争的“默认”实现。
我知道这是一个老问题,所以你可能早就转向其他事情了,这很好。但是,如果您仍在为重构此代码的正确方法而苦苦挣扎,请分享一些有关此类层次结构和此协议继承实际代表的内容的信息,我们可能会提供更具体的建议。这是抽象示例进一步混淆问题的情况之一。让我们看看真正的类型/协议是什么。(如果你有可用的代码,http://codereview.stackexchange.com可能是更好的地方。)
我设法得到它的工作通过定义color上Color和切换执行列表B.没有太多的好,如果B必须是一个A虽然。
protocol Color {
var color : String { get }
}
protocol RedColor: Color {
}
extension Color {
var color : String {
get {return "Default color"}
}
}
extension RedColor {
var color : String {
get {return "Red color"}
}
}
protocol PrintColor {
func getColor() -> String
}
extension PrintColor where Self: Color {
func getColor() -> String {
return color
}
}
class A : Color, PrintColor {
}
class B : RedColor, PrintColor {
}
let a = A().getColor() // "Default color"
let b = B().getColor() // "Red color"
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
28212 次 |
| 最近记录: |