Lazy / inline在Swift中实现协议

时间:2014-09-06 20:12:19

标签: ios swift protocols inline lazy-evaluation

我想懒惰/内联在Swift中实现协议。 因此,在实现方面,我将可以访问协议范围之外的变量,

与在Java中实现接口而不声明类相同:

class MyClass:UIView {
  var someComponent:SomeInnerComponent = SomeInnerComponent();
  var count:Int = 0;

  var a = :SomeProtocol { //<----- IS THIS POSSIBLE, IF YES HOW ?
      func a0() {MyClass.count--}
      func a1() {MyClass.count++}
  } 

  someComponenet.delegate = a;
}

protocol SomeProtocol {
  func a0()
  func a1()
}

编辑----

谢谢我看看这个解决方案,我没有看到如何访问父类的变量。 所有示例都显示了一个Anonymous类,但没有一个示例正在访问父变量。

1 个答案:

答案 0 :(得分:3)

你正在寻找的是一个内部类(不一定是匿名的),在一个范围内声明,允许它访问count实例的MyClass变量,并且采用协议在不同的范围内定义。现在,斯威夫特有一些这样的作品,但看起来你看起来并不像他们想要的那样简洁。

您可能会考虑声明一个内部类:

class MyView: UIView {
    let someComponent = SomeInnerComponent() // type SomeInnerComponent is inferred
    var count = 0 // type Int is inferred
    class Helper: SomeProtocol {
        func a0() { count-- } // ERROR
        // ...
    }
    init() {
        someComponent.delegate = Helper()
    }
}

但这不起作用,因为count隐含self.count,其中selfHelper实例,而不是MyView实例“拥有” “Helper实例。并且没有办法在MyView的方法中引用Helper实例(或其属性),因为您也可以在没有现有的情况下构造MyView.Helper() MyView个实例。 Swift中的内部类(或一般的嵌套类型)仅在词法范围内嵌套,而不是存在所有权。 (或者换句话说,因为你引用了Java:Swift中的所有内部类都像Java中的静态内部类。没有非静态内部类。)如果这是你想要的功能,{{3} }。

您也可以尝试在Helper内声明MyView.init() - 在Swift中,您可以在任何地方嵌套类型定义,包括内部函数或其他类型的方法。在那里定义,它可以引用MyView的属性。但是,现在Helper的类型信息仅在MyView.init()内可见,因此当您将其分配给someComponent.delegate(其类型仅为SomeProtocol)时,您不能利用它...这甚至会使编译器崩溃。 (那是另一个it's probably worth telling Apple you want it,但是很难说这个错误是“编译器在有效使用时崩溃”还是“代码坏了,但编译器崩溃而不是产生错误”。)

我能想出的最接近的解决方案看起来像这样:

class SomeInnerComponent {
    var delegate: SomeProtocol?
}
protocol SomeProtocol {
    func a0()
    func a1()
}
class MyClass  {
    var someComponent = SomeInnerComponent()
    var count = 0
    struct Helper: SomeProtocol {
        var dec: () -> ()
        var inc: () -> ()
        func a0() { dec() }
        func a1() { inc() }
    }
    init() {
        someComponent.delegate = Helper(
            dec: { self.count -= 1 }, // see note below
            inc: { self.count += 1 }
        )
    }
}

工作原理:

  • Helper是一个内部结构(可以是一个类,但结构更简单)
  • 它实现a0a1方法,满足SomeProtocol
  • 的要求
  • a0a1的实现调用闭包decinc,它们是Helper的存储属性(也称为实例变量)结构
  • 在构造Helper实例时(使用默认的成员初始化程序,Helper(dec: (Void -> Void), inc: (Void -> Void))
  • 编写(或以其他方式指定)这些闭包
  • 因为您可以在初始化Helper时编写闭包,所以这些闭包可以捕获您调用初始值设定项的变量,包括引用self实例创建的隐式MyClass Helper

您需要a0 / a1dec / inc,因为您需要用于捕获封闭状态的闭包(后者),而不是方法。即使闭包和funcs /方法在很多方面可以互换,也不能通过为方法/ func名称分配闭包来创建方法/ func实现。 (如果SomeProtocol需要闭包属性而不是方法,那将是一个不同的故事,但我假设SomeProtocol不是你控制的东西。)

无论如何,这可能是一些你可能并不真正需要的样板和抽象层,因此可能值得研究构建代码的其他方法。


注意:我的示例使用了您可能期望{ self.count -= 1 }的闭包{ self.count-- }。后者不起作用,因为这是一个带有值的表达式,因此Swift会将其解释为闭包的返回值的简写。然后它会抱怨你为一个期望() -> Int(又名() -> ())关闭的属性分配了Void -> Void个闭包。使用-= 1可以解决此问题。