swift - 使用闭包属性满足 Swift 协议(protocol)方法?

标签 swift closures protocols

我有一个带有方法的协议(protocol)。我一直以为方法可以用同名的闭包代替,但是好像不行:

protocol Foo {
    func bar() // Type:  Void -> Void
}

class X: Foo {
    func bar() { }
}

class Y: Foo { // Compiler: doesn't conform to protocol Foo
    let bar: Void->Void = {}
}

有没有办法让它工作?我想覆盖测试 stub 实现的方法行为。目前,我必须这样做,我想缩短它:

class Z: Foo {
    var barClosure: Void -> Void = {}

    func bar() {
        barClosure()
    }
}

let baz = Z()
baz.barClosure = { /* ... */ }
baz.bar() // Calls the closure replacement

最佳答案

感谢@Dániel Nagy,我能够弄清楚我有哪些选择。该协议(protocol)应要求关闭。这样,客户端代码就不会改变,因为闭包调用与方法调用相同。

  • 使属性可变,以便实现可以决定是否要锁定该值
  • 只需要一个 setter/getter (出于同样的原因)
  • 在生产代码中将属性初始化为不可变 (let)
  • 在测试代码中将属性初始化为可变 (var) 以在测试用例中提供替代实现,就像模拟观察者所做的那样

这是一个修改后的示例,它通过返回字符串在 Playground 中运行良好:

protocol Foo {
    var bar: () -> String { get }
}

class X: Foo {
    // cannot be overwritten
    let bar: () -> String = { return "default x" }
}

class Y: Foo {
    private let _bar: () -> String = { return "default y" }

    // Can be overwritten but doesn't have any effect
    var bar: () -> String {
        get {
            return _bar
        }
        set {
        }
    }
}

class Z: Foo {
    // Can be overwidden
    var bar: () -> String = {
        return "default z"
    }
}

let bax = X()
bax.bar() // => "default x"
// bax.bar = { /* ... */ } // Forbidden

let bay = Y()
bay.bar() // => "default y"
bay.bar = { return "YY" }
bay.bar() // => "default y"

let baz = Z()
baz.bar() // => "default z"
baz.bar = { return "ZZ" }
baz.bar() // => "ZZ"

关于swift - 使用闭包属性满足 Swift 协议(protocol)方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28496120/

相关文章:

swift - 如果我将 Dispatch.main.async block 放在 Dispatch.global.async 中会发生什么?

ios - 使用 AVPlayer 播放流媒体视频

javascript - 在图层组中放置多个标记

arrays - `forEach((c) => c())` 在 Dart 中是什么意思?

ios - 类(不是实例)充当委托(delegate)是否可能/正确?

ios - 如何在不通知 ios 应用程序的情况下发送数据消息?

ios - 如何访问在 xib 中创建的自定义单元格

java - 无法调用匿名类方法

protocols - NNTP 中的标准 header 是什么?

ios - 关联类型为类的协议(protocol)的扩展?