你要找的是一个内部类(不一定是匿名的),它在一个范围内声明,它允许它访问变量的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
实例。并且没有办法从Helper
的方法中引用该实例(或其属性),因为您可以在没有现有的MyView
实例的情况下构建MyView.Helper()
。 Swift中的内部类(或通常嵌套类型)只能在词法范围内嵌套,而不能在存在所有权中嵌套。 (换句话说,因为你引用了Java:Swift中的所有内部类都像Java中的静态内部类,没有非静态的内部类。)如果这是你想要的功能,但是,it's probably worth telling Apple you want it。
你也可以尝试在MyView.init()
里面声明Helper
- 在Swift中,你可以在任何地方嵌套类型定义,包括函数内部或其他类型的方法。在那里定义,它可以参考MyView
的属性。但是,现在Helper
的类型信息仅在MyView.init()
内部可见,所以当您将其分配给someComponent.delegate
(其类型仅为SomeProtocol
)时,您无法使用它......甚至导致编译器崩溃。 (这是另一个bug to report,但很难说错误是真的“编译器崩溃的有效用法”或“代码不好,但编译器崩溃,而不是产生错误”。)
最接近的解决方案,我能想出看起来是这样的:
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
是内部结构(可能是一类,而是一个结构是更简单)
- 它实现了
a0
和a1
方法,满足的要求SomeProtocol
- 个该的
a0
实现a1
电话接到关闭dec
和inc
,这是本Helper
结构的存储特性(又名实例变量)
- 当你构建一个
Helper
实例(使用你写的(或规定),这些关闭默认成员明智的初始化,Helper(dec: (Void -> Void), inc: (Void -> Void))
)
- 因为你可以初始化
Helper
时写的封锁,关闭那些可以捕捉你在哪里调用初始化变量,包括指MyClass
实例创建Helper
隐含self
。
同时需要a0
/a1
和dec
/inc
,因为你需要关闭(后者),而不是方法,捕捉封闭状态。即使闭包和funcs /方法在很多方面是可以互换的,但是你不能通过给方法/ func名称赋一个闭包来创建一个方法/ func实现。 (这将会是一个不同的故事,如果需要封闭性的,而不是方法SomeProtocol
,但我假设SomeProtocol
是不是你的控制之下的东西。)
无论如何,这是一种很多的样板和一层您可能并不真正需要的抽象,因此可能需要寻找其他方法来构建代码。
注:我的例子中使用了封闭{ self.count -= 1 }
下,您可能希望{ self.count-- }
。后者不起作用,因为这是一个带有值的表达式,所以Swift会将其解释为闭包返回值的简写。然后它会抱怨说,您为() ->()
(又名Void -> Void
)关闭的房产分配了() -> Int
闭合。改用-= 1
来解决这个问题。
注意,所有上讨论关闭其他问题的答案还解决您的问题关于“获得变数协议范围之内。”闭包可以捕获和修改这些变量。 – 2014-09-07 02:38:09
谢谢我看这个解决方案,我没有看到如何访问父类的变量。 所有示例都显示Anonymous类,但没有一个示例访问父变量。 – 2014-09-07 17:43:22