懒/内联在Swift中实现协议

害你

我想在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()
}

编辑----

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

rick

您正在寻找的是一个内部类(不一定是匿名类),该类在一个范围内声明,该范围允许它访问实例count变量MyClass,并采用在另一个范围内定义的协议。目前,Swift包含了其中的一些内容,但看起来似乎您无法以所需的任何简洁方式将它们放在一起。

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

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,这里self是一个Helper实例,而不是MyView“拥有”的实例Helper的实例。而且,没有一种方法可以MyView的方法中引用该实例(或其属性)Helper,因为您可以在MyView.Helper()没有现有MyView实例的情况下构造一个Swift中的内部类(或通常的嵌套类型)仅在词汇范围内嵌套,而在存在所有权上不嵌套。(或者换一种说法,因为您引用了Java:Swift中的所有内部类都像Java中的静态内部类。没有非静态内部类。)但是,如果您要使用此功能,可能值得一讲苹果要

您也可以尝试在Helper内部声明MyView.init()-在Swift中,您可以在任何地方嵌套类型定义,包括内部函数或其他类型的方法。在此处定义,它可以引用MyView的属性。但是,现在for的类型信息Helper仅在中可见MyView.init(),因此当您将其分配给someComponent.delegate(类型为SomeProtocol)时,就无法使用它……这甚至使编译器崩溃。(这是另一个要报告错误,但是很难说该错误是“在有效使用情况下编译器崩溃”还是“代码不好,但是编译器崩溃而不是产生错误”。)

我能想到的最接近的解决方案如下所示:

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))
  • 由于您可以在初始化a时编写闭包Helper,因此这些闭包可以捕获您正在调用初始化程序的变量,包括self指向MyClass创建的实例的隐式变量Helper

您需要a0/a1dec/,inc因为您需要闭包(后者)而不是方法来捕获封闭状态。即使闭包和函数/方法在许多方面可以互换,您也无法通过将闭包分配给方法/函数名称来创建方法/函数实现。(如果SomeProtocol需要闭包属性而不是方法,那将是另外一回事了,但我认为SomeProtocol这不是您所能控制的。)

无论如何,这可能是很多样板和您可能不需要的抽象层,因此可能值得研究构建代码的其他方法。


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

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

在Swift中实现Objective C协议

来自分类Dev

Xcode中的自动实现Swift协议方法

来自分类Dev

在基类中实现Swift协议方法

来自分类Dev

在Swift中实现闭包协议

来自分类Dev

在 Swift 中实现 Objective-C 协议

来自分类Dev

不要将标签内联在表单内联中-Bootstrap

来自分类Dev

Swift 协议扩展默认实现与类中的实际实现

来自分类Dev

先进的Swift2-V类中的实现协议与Struct中的实现协议

来自分类Dev

CSS中的SVG内联在FireFox中不起作用

来自分类Dev

内联在熊猫中的两个专栏

来自分类Dev

在Swift中实现协议中定义的下标时出错

来自分类Dev

检查是否在Swift中实现了可选的协议方法?

来自分类Dev

NSManagedObject在Swift中实现协议的EXC_BAD_ACCESS错误

来自分类Dev

NSManagedObject在Swift中实现协议的EXC_BAD_ACCESS错误

来自分类Dev

Swift中协议扩展的默认实现不起作用

来自分类Dev

如何实现Swift的Comparable协议?

来自分类Dev

Swift:实现协议的类的类型

来自分类Dev

Swift:在协议扩展的静态变量中存储协议的实现类型

来自分类Dev

Midje中的模拟协议实现

来自分类Dev

协议中的方法未实现

来自分类Dev

错误-在Elixir中实现协议

来自分类Dev

在Swift中采用协议

来自分类Dev

Swift中的协议扩展?

来自分类Dev

在Swift中定义协议

来自分类Dev

Swift中的协议集

来自分类Dev

Swift中的协议集

来自分类Dev

内联在 CSS 中的 SVG 在 Chrome/Edge 中有效,但在 Firefox 中无效

来自分类Dev

如何使用内联在同一块中的元素显示 Bootstrap 网格视图?

来自分类Dev

无法使用具体的子类在Swift中的协议中实现属性