我们可以在协议扩展中使用方法参数的默认值吗?如果可以,我们是否可以在实现该协议的结构上覆盖这些方法?

时间:2019-01-29 17:35:35

标签: swift protocols

我们可以在协议扩展中使用方法参数的默认值吗?

如果可以的话,我们可以在实现该协议的结构上覆盖那些方法吗?

我正在做,但是结果出乎意料。这是为什么?谢谢!

import Foundation

protocol Datasource {
    func getLetter(_ uppercased: Bool) -> String
}

extension Datasource {

    func getLetter(_ uppercased: Bool = true) -> String {
        return uppercased ? "B" : "b"
    }
}

struct ADatasource: Datasource {

    func getLetter(_ uppercased: Bool = true) -> String {
        return uppercased ? "A" : "a"
    }
}

let datasource: Datasource = ADatasource()
datasource.getLetter(true) // returns "A"
datasource.getLetter()     // returns "B"   

2 个答案:

答案 0 :(得分:1)

老实说,不确定.getLetter()为什么选择覆盖已实现的协议扩展。

但是,我知道有一个很好的解决方法可以实现您要执行的操作:

protocol Datasource {
    func getLetter(_ uppercased: Bool) -> String
}

extension Datasource {

    func getLetter() -> String {
        return getLetter(true)
    }

    func getLetter(_ uppercased: Bool) -> String {
        return uppercased ? "B" : "b"
    }
}

struct ADatasource: Datasource {

    func getLetter(_ uppercased: Bool) -> String {
        return uppercased ? "A" : "a"
    }
}

let datasource: Datasource = ADatasource()
datasource.getLetter(true) // returns "A"
datasource.getLetter()     // now returns "A"

答案 1 :(得分:1)

如果我没记错的话,这是因为动态调度与静态调度有关。协议扩展中声明的方法不会动态调度。

由于没有在协议中定义没有显式参数的方法,因此将以静态方式调度该调用。并且由于您已将datasource定义为类型Datasource,所以将调用协议的实现而不是ADatasource的实现。

如果删除显式类型并仅使用let datasource = ADatasource(),它将按预期工作。