我正在试验Swift协议扩展,我发现这种行为非常令人困惑.你能帮我怎么得到我想要的结果吗?

请参阅代码最后4行的注释.(如果需要,可以将其复制粘贴到Xcode7playground ).非常感谢.

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"

推荐答案

简单的回答是,协议扩展不执行类多态性.这是有一定意义的,因为协议可以被 struct 或枚举采用,而且我们不希望仅仅采用协议就在不必要的地方引入动态调度.

因此,在getColor()中,color实例变量(可以更准确地写为self.color)并不意味着你认为它是什么,因为你是从多态性的Angular 考虑类,而协议不是.所以这是可行的:

let colorB = B().color // is "Red color" - OK

...因为你要求class解决color,但这并没有达到你的预期:

let b = B().getColor() // is "Default color" BUT I want it to be "Red color"

...因为getColor方法完全是在协议扩展中定义的.您可以通过在B中重新定义getColor来解决此问题:

class B: A, RedColor {
    func getColor() -> String {
        return self.color
    }
}

现在这个类的getColor被称为,它对self有一个多态的概念.

Swift相关问答推荐

从`compactMap()`闭包返回`nil`未通过结果类型判断

Swift通过设置变量B自动设置变量A的值

关闭 SwiftUI TabView 中的子视图

Xcode 15 Beta中如何使用@Observable?

如何在SwiftUI中更改NSTextView中的 Select colored颜色 ?

(Swift)混淆了函数内 for-in 循环的返回值和循环后(函数内)的返回值)

如何删除快速处理消息

If 语句在 Swift 中有 2 个日期

有没有更快的方法来循环浏览 macOS 上已安装的应用程序?

有什么方法可以快速为泛型参数分配默认值?

如何更改 Picker 的边框 colored颜色

是否可以使任何协议符合 Codable?

任何使 ScrollView 像 List 一样执行更灵活的修饰符?

如何在 Swift 中将 XPC 自定义类列入白名单?

Swift 读写图片占用大量内存

Swift 函数 vs 惰性变量 vs 计算(computed)属性 - 区别?

在 Swift 中返回实例类型

在 Swift for iOS 中沿圆形路径绘制文本

用 UIBezierPath 画一条线

为 UIImagePicker 设置委托返回错误